更新数组状态时,我的上下文状态出现问题。
问题如下,我有一个对象存储用户选择的日期,并且可以一一删除。删除一个时,它不会更新反应状态,也不会执行 useEffect。
// context/index.tsx
export const MyAppContext = ({children}: any) => {
const [afterSchool, setAfterSchool] = useReducer(afterSchoolReducer, initialAfterSchoolState);
return (
<AppContext.Provider value={{afterSchool, setAfterSchool}}>
{children}
</AppContext.Provider>
)
}
// context/reducer/after-school.reducer.ts
export const afterSchoolReducer = (state: IAfterSchoolState, action: IAfterSchoolAction): IAfterSchoolState => {
const { type, payload } = action;
switch (type) {
case 'removeSchedule': {
const { removeDate } = payload;
if (!removeDate) return state;
const updatedSelectedDays = state.type.selectedDays.filter(date => date !== removeDate);
return {
...state,
type: {
...state.type,
selectedDays: [...updatedSelectedDays],
},
};
};
case "updateServiceTypes":
console.log("updateServiceTypes type:", state.type)
const newTypes = state.service.types.map(type =>
(type.id === state.type.id)
? state.type
: type
);
return {
...state,
service: {
...state.service,
types: newTypes
}
};
default:
return state;
}
// hooks/after-school.ts
export const useAfterSchool = () => {
const { afterSchool: { type, service }, setAfterSchool } = useAppContext();
const handleDateRemove = (date: string) => {
setAfterSchool({ type: "removeSchedule", payload: { removeDate: date } });
setAfterSchool({ type: "updateServiceTypes", payload: {} });
};
useEffect(() => {
console.log("type:", type);
}, [type]);
}
React 可能不会导致重新渲染,因此,如果您几乎同时在同一个对象上执行两个不同的操作,则
useEffect
不会触发。我建议重构您的代码库以对数组执行单个操作,而不是两个后续操作:
将您的行动融为一体
// context/reducer/after-school.reducer.ts
export const afterSchoolReducer = (state: IAfterSchoolState, action: IAfterSchoolAction): IAfterSchoolState => {
const { type, payload } = action;
switch (type) {
case 'removeSchedule': {
const { removeDate } = payload;
if (!removeDate) return state;
const updatedSelectedDays = state.type.selectedDays.filter(date => date !== removeDate);
const newTypes = state.service.types.map(t =>
(t.id === state.type.id)
? { ...state.type, selectedDays: updatedSelectedDays }
: t
);
return {
...state,
type: {
...state.type,
selectedDays: updatedSelectedDays,
},
service: {
...state.service,
types: newTypes
}
};
}
default:
return state;
}
};
重构钩子
// hooks/after-school.ts
export const useAfterSchool = () => {
const { afterSchool: { type }, setAfterSchool } = useAppContext();
const handleDateRemove = (date: string) => {
setAfterSchool({ type: "removeSchedule", payload: { removeDate: date } });
};
useEffect(() => {
console.log("type:", type);
}, [type.selectedDays]); // React will re-trigger on `selectedDays` change
}
另请注意,useEffect 现在依赖于
type.selectedDays
来重新触发。