React useContext 和 useReducer - 在应用程序中需要全局状态,对使用一个与多个 reducer 感到困惑
React useContext & useReducer - Need global state in app, confused about using one vs multiple reducers
我需要在我的应用程序中共享一些信息,例如用户详细信息、头像和应用程序内提醒。我担心我可能没有以正确的方式使用 useReducer 和 useContext,因为我只是将所有内容都订阅到这个 reducer 并将其用作一个巨大的全局状态设置函数。我应该以不同的方式处理这个问题吗?
const initialState : IStore = { isLoading : true, isSignedIn : false, newUser : false, hero : null, alerts : [] };
const store = createContext<IStore>(initialState);
const { Provider } = store;
const StateProvider : React.FC = ( { children } ) => {
const [state, dispatch] = useReducer((state : IStore, action : IAction) => {
switch(action.type) {
case 'TOGGLE LOADING': {
const { isLoading } = action.payload;
if(typeof isLoading === 'undefined'){
return Object.assign({}, state, { isLoading : !state.isLoading });
}
return Object.assign({}, state, { isLoading });
}
case 'SET EXISTING USER INIT DATA': {
const { user, hero, gameItems, latestBattle, isSignedIn } = action.payload;
return { ...state, ...{ user, hero, gameItems, latestBattle, isSignedIn } };
}
case 'SET ISSIGNEDIN': {
const { isSignedIn } = action.payload;
return { ...state, isSignedIn };
}
case 'SET NEW USER': {
const { newUser } = action.payload;
return { ...state, newUser };
}
case 'SET HERO': {
const { hero } = action.payload;
return { ...state, hero };
}
case 'SET USER': {
const { user } = action.payload;
return { ...state, user };
}
case 'SET ALERTS': {
const { alerts } = action.payload;
return { ...state, alerts : [...alerts] };
}
case 'REMOVE ALERTS': {
const { indiciesForRemoval } = action.payload;
return { ...state, alerts :
state.alerts.filter((alert) => {
return !indiciesForRemoval.includes(alert.index);
})
};
}
default:
throw new Error('In Store default, should not happen.');
};
}, initialState);
return (
<Provider value={{ state, dispatch }}>
{children}
</Provider>
);
};
更多的是代码质量问题:
- 将所有这些数据和相关操作存储在这个单一的减速器中是否有意义?
- 将 reducer 拆分为多个 reducer 会更符合逻辑 and/or 可维护吗?
- 如果我将这个减速器的一部分移动到一个单独的减速器中,它可以在其他地方重复使用吗?
如果您只使用一点状态和少量操作,那么单个减速器就可以了。您必须注意的一件事是重新渲染触发:每当您的 reducer 的状态更新时,每个使用该 reducer 的组件都必须重新渲染。对于小州来说,这不是问题,但是如果您例如有很多复杂的组件需要 state.fieldA
和很多复杂的组件需要 state.fieldB
,那么它可能值得拆分。否则更新 fieldA
也会触发所有仅对 fieldB
感兴趣的组件的重新渲染。 尽管可以进行某些优化以部分抵消这种情况。
我需要在我的应用程序中共享一些信息,例如用户详细信息、头像和应用程序内提醒。我担心我可能没有以正确的方式使用 useReducer 和 useContext,因为我只是将所有内容都订阅到这个 reducer 并将其用作一个巨大的全局状态设置函数。我应该以不同的方式处理这个问题吗?
const initialState : IStore = { isLoading : true, isSignedIn : false, newUser : false, hero : null, alerts : [] };
const store = createContext<IStore>(initialState);
const { Provider } = store;
const StateProvider : React.FC = ( { children } ) => {
const [state, dispatch] = useReducer((state : IStore, action : IAction) => {
switch(action.type) {
case 'TOGGLE LOADING': {
const { isLoading } = action.payload;
if(typeof isLoading === 'undefined'){
return Object.assign({}, state, { isLoading : !state.isLoading });
}
return Object.assign({}, state, { isLoading });
}
case 'SET EXISTING USER INIT DATA': {
const { user, hero, gameItems, latestBattle, isSignedIn } = action.payload;
return { ...state, ...{ user, hero, gameItems, latestBattle, isSignedIn } };
}
case 'SET ISSIGNEDIN': {
const { isSignedIn } = action.payload;
return { ...state, isSignedIn };
}
case 'SET NEW USER': {
const { newUser } = action.payload;
return { ...state, newUser };
}
case 'SET HERO': {
const { hero } = action.payload;
return { ...state, hero };
}
case 'SET USER': {
const { user } = action.payload;
return { ...state, user };
}
case 'SET ALERTS': {
const { alerts } = action.payload;
return { ...state, alerts : [...alerts] };
}
case 'REMOVE ALERTS': {
const { indiciesForRemoval } = action.payload;
return { ...state, alerts :
state.alerts.filter((alert) => {
return !indiciesForRemoval.includes(alert.index);
})
};
}
default:
throw new Error('In Store default, should not happen.');
};
}, initialState);
return (
<Provider value={{ state, dispatch }}>
{children}
</Provider>
);
};
更多的是代码质量问题:
- 将所有这些数据和相关操作存储在这个单一的减速器中是否有意义?
- 将 reducer 拆分为多个 reducer 会更符合逻辑 and/or 可维护吗?
- 如果我将这个减速器的一部分移动到一个单独的减速器中,它可以在其他地方重复使用吗?
如果您只使用一点状态和少量操作,那么单个减速器就可以了。您必须注意的一件事是重新渲染触发:每当您的 reducer 的状态更新时,每个使用该 reducer 的组件都必须重新渲染。对于小州来说,这不是问题,但是如果您例如有很多复杂的组件需要 state.fieldA
和很多复杂的组件需要 state.fieldB
,那么它可能值得拆分。否则更新 fieldA
也会触发所有仅对 fieldB
感兴趣的组件的重新渲染。 尽管可以进行某些优化以部分抵消这种情况。