使用React的一些知识点2

61 阅读2分钟

将组件中的业务逻辑提取到reduxreducer

先来看一个组件(视图)中包含太多业务逻辑的例子:

// .app/modules/someModule/MyComponent.js
import * as Actions from './actions';
import {connect} from 'react-redux';

class MyComponent extends React.Component{

  componentDidMount() {
    const {someState, otherState, someStateNotToBeRendered, dispatch, someValueFromComponent} = this.props;

    //bad, 业务逻辑
    //这里根据someState, otherState, someStateNotToBeRendered上的数据和从其他组件传递过来的属性someValueFromComponent做了很多业务逻辑处理
    //最后得到了`init`这个`action`需要的参数
    const finalValue = bussinessLogic(someState, otherState, someStateNotToBeRendered, someValueFromComponent);

    //if条件判断语句也可能是业务逻辑判断,还有几个同步action, 应该移动到actionCreator中,
    dispatch(Actions.actionOne());
    dispatch(Actions.actionThree());
    if(finalValue === 'someValue') {
      dispatch(Actions.initialize(finalValue));
    }

  }

  handleClick = () => {
    const {someState, otherState, dispatch} = this.props;

    //bad, 业务逻辑
    //这里用someState和otherState上的数据做了很多逻辑处理
    const finalValue = caculateFinalValue(someState, otherState);
    dispatch(Actions.someAction(finalValue));

    //bad, dispatch了很多action
    dispatch(Actions.actionOne());
    //使用了promise middleware的action
    dispatch(Actions.actionTwo()).then((state) => {

      const {someState: newSomeState, otherState: newOtherState} = state;

      const finalValueAgain = caculateSomeFinalValue(newSomeState, newOtherState);

      dispatch(Actions.actionThree(finalValueAgain));
    });
  }

  render() {
    const {someState} = this.props;
    const {someData} = someState;

    //bad, 业务逻辑
    const someDataFormat = Util.dataFormat(someData);

    return (
      <div>{someDataFormat}</div>
    )
  }
}

export default connect(s => ({
  someState: s.someState,

  //bad
  otherState: s.otherState
  someStateNotToBeRendered: s.someStateNotToBeRendered
})
)(MyComponent);
// ./app/modules/someModule/actions.js
export const actionOne = () => ({
  type: 'actionOne'
});

export const actionTwo = () => ({
  type: 'actionTwo'
});

export const actionThree = (value) => ({
  type: 'actionThree'
});

export const someAction = () => ({
  type: 'someAction'
})

export const initialize = (value) => ({
  type: 'initialize',
  params: value
})
  • 使用react-reduxconnect高阶组件给组件注入redux``store上的数据时,应该只注入该组件需要渲染的数据,因为view层仅仅需要渲染的数据。上面的例子中给组件props上注入的someStateNotToBeRenderedotherState,组件并不需要渲染这两个数据,仅仅是为了做业务逻辑处理,在componentDidMount中构造了init``action需要的参数。导致的问题就是,组件mount后,当这两个数据经过各自的reducer返回各自新的引用时,组件会走componentWillReceiveProps,最后再次render一遍,这显然是不合理的。
  • 对于上述例子中componentDidMountbussinessLogic这个构造action参数的逻辑,我们应该将构造参数的代码放在redux-thunk中,见后面的例子。
  • 这里我们需要使用redux-thunk中间件进行改造
// ./app/modules/someModule/MyComponent.js
import * as Actions from './actions';
import {connect} from 'react-redux';

class MyComponent extends React.Component{
  componentDidMount() {
    const {dispatch} = this.props;
    dispatch(Actions.init());
  }

  handleClick = () => {

  }

  render() {
    const {}
    return (
      <div></div>
    )
  }
}

export default connect(s => ({
  someState: s.someState
}))(MyComponent);
// ./modules/someModule/action.js
export const actionOne = () => ({
  type: 'actionOne'
});

export const actionTwo = () => ({
  type: 'actionTwo'
});

export const actionThree = (value) => ({
  type: 'actionThree'
});

export const someAction = () => ({
  type: 'someAction'
})

export const initialize = (value) => ({
  type: 'initialize',
  params: value
})

export const init = (params) => {

  const someValueMayBeUse = '';

  return (dispatch, getState) => {

    dispatch(actionOne());
    dispatch(actionThree());

    const {otherState, someStateNotToBeRendered, someState} = getState();

    const finalValue = bussinessLogic(someState, otherState, someStateNotToBeRendered);

    //流程控制
    if(someState.isShow) {
      dispatch(actionTwo());
    }

    if(finalValue === 'someValue') {
      dispatch(initialize(finalValue));
    }

    dispatch(someAsyncAction()).then(() => {
      dispatch(fxxk());
    })

  }
}
  • init actionCreator通过redux-thunk整合了actionOneactionTwoinitialize三个actionCreatorinitialize这个actionCreator需要一个参数,这个参数是通过store上的otherStatesomeStateNotToBeRenderedsomeState这三个数据,进行一些逻辑处理(bussinessLogic)得出的,通过redux-thunkgetState方法,我们可以得到当前store,从而取得store上需要的数据,进行下一个actionCreator的参数构造,或者进行一些流程控制。

以上就是我在实际使用react中的一些小总结。