用Redux来进行组件间通讯

前端之家收集整理的这篇文章主要介绍了用Redux来进行组件间通讯前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

用Redux来进行组件间通讯

demo地址

疑惑

之前在做项目的时候,一直会遇到一个困扰我的问题,两个互相独立的子组件如何通讯?

假设现在结构如下

ListItem是一个todoList组件,里面有一个删除操作,点击添加备注时会弹出模态框,让用户进行填写。

按照以前的写法,要像这样

  1. 父组件要传递一个props:showDelModal,以便于todoItem调起模态框。

  2. 同时,父组件要传递confirmcancel两个props给Modal组件,用于接收Modal组件点击了确认还是取消。

假设这样的子组件较多,那父组件就显得很臃肿,阅读代码也很麻烦,我希望调用确认模态框时就像调用window.confirm一样,逻辑清晰,不需要这么多的回调函数

实现

用了redux后,发现我的思路是可以被实现的,下面讲一下过程,建议和代码一起看。

我们新建一个modal组件

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import '../stylus/modal.styl';
  4.  
  5. export default class ConfirmModal extends React.Component {
  6. constructor() {
  7. super();
  8. }
  9.  
  10. componentDidMount() {
  11.  
  12. }
  13.  
  14.  
  15.  
  16. onConfirm() {
  17.  
  18. this.props.resolve(true);
  19. }
  20.  
  21. onCancel() {
  22. this.props.reject(false);
  23.  
  24. }
  25.  
  26. render() {
  27. return (
  28. <div className="modal" style={{display: this.props.show ? 'block' : 'none'}}>
  29. <div className="modal-inner">
  30. <h3>确认删除?</h3>
  31. <div className="btn-action">
  32. <button className="pure-button" onClick={this.onConfirm.bind(this)}>确认</button>
  33. <button className="pure-button" onClick={this.onCancel.bind(this)}>取消</button>
  34. </div>
  35. </div>
  36. </div>
  37. )
  38. }
  39.  
  40. }

修改原有todoItem的del函数

  1. //重点在这
  2. waitForConfirm() {
  3.  
  4. let {store} = this.context;
  5.  
  6. return new Promise((resolve,reject) => {
  7.  
  8. store.dispatch({
  9. type: 'SHOW_MODAL',payload: {
  10. show: true,resolve,reject
  11. }
  12. })
  13.  
  14. });
  15. }
  16.  
  17. closeModal() {
  18. let {store} = this.context;
  19.  
  20.  
  21. store.dispatch({
  22. type: 'CLOSE_MODAL',payload: {}
  23. })
  24.  
  25. }
  26.  
  27. async del() {
  28. let {index} = this.props;
  29.  
  30. let ret = await this.waitForConfirm().catch(e => {
  31. return false;
  32. });
  33.  
  34. if (!ret) {
  35. this.closeModal();
  36. return false;
  37. }
  38.  
  39. this.props.handleDelTodo(index);
  40.  
  41. this.closeModal();
  42.  
  43.  
  44. }

原有的reducer上增加数据

  1. /**
  2. * Created by chenchen on 2017/2/4.
  3. */
  4.  
  5. import {combineReducers} from 'redux';
  6.  
  7.  
  8. function todoList(todolist = [],action) {
  9. switch (action.type) {
  10. case 'ADD_TODO':
  11. return [...todolist,...action.payload];
  12. return todolist;
  13. case 'DEL_TODO':
  14. return todolist.filter((val,index) => index !== action.payload);
  15. default:
  16. return todolist;
  17. }
  18.  
  19. }
  20.  
  21. //确认删除模态框
  22. function confirmModalData(data = {
  23. show: false,resolve: null,reject: null
  24. },action) {
  25. let d = {};
  26. switch (action.type) {
  27. case 'SHOW_MODAL':
  28. return Object.assign(d,data,action.payload);
  29. case 'CLOSE_MODAL':
  30. return Object.assign(d,{show: false});
  31. default:
  32. return data;
  33. }
  34. }
  35.  
  36. //... 其他reducer
  37.  
  38. export default combineReducers({todoList,confirmModalData});

下面这种写法,是不是就很像window.confirm呢?

  1. let ret = await this.waitForConfirm().catch(e => {
  2. return false;
  3. });

原理

其实原理还是用了回调函数,只是将其包裹在一个Promise对象中:
把Modal的confirmcancel放入Redux的store中,每个todoItem进行删除操作时,会替换store中的resolvereject函数,并返回一个Promise对象,而Modal进行确认和取消操作,会调用store中的resolvereject函数,这样,todoItem等待模态框的Promise就返回啦,通过返回值就可以判断是确认和取消操作了。

这样的好处就是,即使组件的层级再深,也不会增加数据传递的复杂度,因为两者是直接通过store来通讯的。

猜你在找的React相关文章