如何在多个通用组件之间共享/拆分Redux Store?

时间:2020-02-08 20:15:40

标签: reactjs react-native redux react-redux state

我有一个称为“ VendorResults”的通用组件。我正在将字符串道具传递给这些通用组件,例如“ Microsoft”,“ Apple”等。

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

在这个通用组件中,我将供应商prop作为参数传递给我的Redux-Thunk操作,例如:

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

API调用开始,并调度Thunk操作。数据最终进入减速器并存储。但是,当我有多个通用Vendor组件时,无论哪个异步调用最后完成,似乎都优先于所有其他异步组件。例如,如果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存储共享/拆分/分区为供应商特定的块,以保持状态分离,但仍然受益于一个流程。谢谢!!

2 个答案:

答案 0 :(得分:1)

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

否则,您需要嵌套reducer:

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作为参数并将其传递给reducer:

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

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

答案 1 :(得分:0)

但是,当我有多个通用Vendor组件时,无论哪个异步调用最后完成,它似乎都优先于所有其他组件。例如,如果oracle完成最后一次加载,则Microsoft组件的状态将更改并显示oracle数据。

您看到的是Oracle数据,因为在获取供应商数据之后,您将使用最新的供应商项目数组覆盖整个供应商状态。

  case FETCH_VENDOR_SUCCESS: return {payload: action.payload.data}

为避免这种情况,您需要将以前的状态与新的状态合并。

解决方案取决于每个供应商的响应。正如根纳迪(Gennady)所建议的,您可以使用一个对象,并使每个供应商成为该对象的属性。

使用平面阵列存储所有不同的供应商商品会带来挑战。您如何确定供应商是否已被提取?

为避免覆盖以前的供应商,您需要将新状态与以前的状态合并。例如

  case FETCH_VENDOR_SUCCESS: return [...state.data, ...payload.data]