我有一个称为“ 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存储共享/拆分/分区为供应商特定的块,以保持状态分离,但仍然受益于一个流程。谢谢!!
答案 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]