Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react复用复杂组件(使用了redux)相关资料整理 #15

Open
leopen-hu opened this issue Sep 12, 2018 · 5 comments
Open

react复用复杂组件(使用了redux)相关资料整理 #15

leopen-hu opened this issue Sep 12, 2018 · 5 comments

Comments

@leopen-hu
Copy link
Owner

leopen-hu commented Sep 12, 2018

《React、Redux与复杂业务组件的复用》

@leopen-hu
Copy link
Owner Author

@leopen-hu
Copy link
Owner Author

@leopen-hu
Copy link
Owner Author

决定在调用action时传递「组件id」参数,在reducer中处理该id,saga中将该id透传给reducer。
优点:清晰且无需引入其他
缺点:写代码的时候需要带组件id,即书写的时候和以前不太一样了。

@leopen-hu
Copy link
Owner Author

leopen-hu commented Nov 23, 2018

对action的创建,reducer的处理进行了封装如下:

// action.js
const createAction = (actionType) => (data => {
  const { componentId, ...param } = data;
  return {
    componentId,
    type: actionType,
    payload: param
  };
});

export const getSomething = createAction(types.GET_SOMETHING.REQUEST);

// reducer.js
const getState = (componentId, state) => (cardId ? clone(state)[componentId] : clone(state));

const setState = (componentId, newState, oldState) => (
  componentId ? {
    ...oldState,
    [componentId]: newState
  } : newState
);

@leopen-hu
Copy link
Owner Author

leopen-hu commented Nov 23, 2018

对于组件内屏蔽componentId带来的影响,有两种方案:

  1. 对mapStateToProps和mapDispatchToProps进行处理;
// mapDispatchToProps
export const mapDispatchToPropsFactory = (actionObjects) => ((dispatch, ownProps) => {
  const { componentId } = ownProps;
  const result = {};
  Object.keys(actionObjects).forEach(actionKey => {
    result[actionKey] = (data) => {
      dispatch(actionObjects[actionKey]({
        componentId,
        ...data
      }));
    };
  });
  return result;
});

// mapStateToProps
const getState = (state, stateGetter) => {
  const getterMap = {
    string: () => getStateByPath(state, stateGetter),
    function: () => stateGetter(state)
  };

  const _stateGetter = getterMap[typeof stateGetter]; // 此方法就不贴出来了
  return stateGetter ? _stateGetter() : {};
};

export const mapStateToPropsFactory = (componentType, needMapStates) => ((state, ownProps) => {
  const { componentId } = ownProps;
  // 当前组件的 state
  const currentState = componentId ? state[componentType][componentId] : state[componentType];
  // 其他组件的 state,这里需要注意,没有屏蔽其他组件的 componentId 的影响
  const toMapStates = {};
  forEach(needMapStates, (stateGetter, propName) => {
    toMapStates[propName] = getState(state, stateGetter);
  });

  return {
    ...toMapStates,
    componentType: currentState
  };
});

// enhance
export const enhance = (component, componentType, needMapStates, needMapActions) => {
  const mapStateToProps = mapStateToPropsFactoryForCard(needMapStates);
  const mapDispatchToProps = mapDispatchToPropsFactoryForCard(needMapActions);
  return compose(connect(mapStateToProps, mapDispatchToProps)(component));
};

// component中使用
export class MyComponent {
  // ...
  const needMapStates = {
    // mapStateToProps 已经默认绑定了当前组件的state,如果需要部分 selector,可以改造该函数
   otherState1: state => state.OtherState.state1
  };
  const needMapActions = {
    getSomething
  };

  export default enhance(MyComponent, 'MyComponent', needMapStates, needMapActions);
}
  1. 使用高阶组件处理,其实和1方法异曲同工,不过做改造时没有理解HOC,故没有使用这种方法。实际上就是在componentDidMount中处理enhance函数的功能并作为props传给子组件

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant