首页 > 解决方案 > 如何在多个通用组件之间共享/拆分 Redux Store?

问题描述

我有一个名为“VendorResults”的通用组件。我将一个字符串 prop 传递给这些通用组件中的每一个,例如“Microsoft”、“Apple”等。

    <ScrollView>
     <SearchResults/>
     <VendorResults vendor={"microsoft"}/>
     <VendorResults vendor={"oracle"}/>
    </ScrollView>

在这个通用组件中,我将 vendor prop 作为参数传递给我的 Redux-Thunk 操作,如下所示:

  componentDidMount() {
     const {vendor} = this.props;
     this.props.getVendorInformation(vendor);
  }

启动 API 调用,并调度 Thunk 操作。数据最终会进入 Reducer 并存储。但是,当我有多个通用供应商组件时,无论哪个异步调用最后完成,似乎都优先于所有其他组件。例如,如果 oracle 最后完成加载,则 microsoft 组件的状态将更改并显示 oracle 数据。

行动

  export function getVendorInformation(vendor) {

  const url = `${VENDOR_URL}api/search/${vendor}`;

  return dispatch => {
    dispatch(getVendor());
    fetch(url)
      .then(blob => blob.json())
      .then(data => {
        dispatch(getVendorSuccess(data))
      })
      .catch(e => {
        console.log(e);
        dispatch(getVendorError(e.message))
      });
  };

减速器

export default function(state=initialState, action){
    switch (action.type){
        case FETCHING_VENDOR: return {payload:[], fetching: true}
        case FETCH_VENDOR_SUCCESS: return {payload: action.payload.data}
        case VENDOR_ERROR: return {payload:[], error: true, ...state}
    }
    return state;
}

我的问题:

我想保持这种通用/可重用供应商组件的模式——我不希望每个供应商都有一个新组件。动作/减速器也是如此;独特的供应商行动/减少者会变得混乱。

如何将单个 Redux 存储共享/拆分/分区为供应商特定的块以保持状态分离,但仍从一个流程中受益。谢谢!!

标签: reactjsreact-nativereduxreact-reduxstate

解决方案


您需要通过操作将供应商传递给减速器并重新执行您的状态结构。如果供应商列表是预先确定的并且不是很长,那么仅创建单独的操作/减速器可能不会那么混乱。

否则,您需要嵌套减速器:

const supportedActions = [FETCHING_VENDOR, FETCH_VENDOR_SUCCESS, VENDOR_ERROR];

const initialVendorState = {data:[], fetching: false, error: false};

const vendorReducer = (state = initialVendorState, action) => {
    switch (action.type){
        case FETCHING_VENDOR: return {data:[], fetching: true}
        case FETCH_VENDOR_SUCCESS: return {data: action.payload.data}
        case VENDOR_ERROR: return {...state, data:[], error: true}
    }
    return state;
}

const reducer = (state = {}, action) => {
  if (supportedActions.includes(action.type)) {
    const s = {};
    s[action.payload.vendor] = vendorReducer(state[action.payload.vendor], action);
    return {
      ...state,
      ...s
    };
  }

  return state
}

export default reducer;

并且您的动作创建者应该将vendor其作为参数并将其传递给减速器:

const fetchVendorSuccess = (vendor, data) => ({
  type: FETCH_VENDOR_SUCCESS,
  payload: {
    vendor,
    data
  }
});

在您的函数中,如果 state 没有关于该供应商的任何信息,connect您将需要使用 smth like来避免错误data: (state[vendor] || {}).data


推荐阅读