更新数组时上下文问题

问题描述 投票:0回答:1

更新数组状态时,我的上下文状态出现问题。

问题如下,我有一个对象存储用户选择的日期,并且可以一一删除。删除一个时,它不会更新反应状态,也不会执行 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]);
}
javascript reactjs typescript react-hooks
1个回答
0
投票

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
来重新触发。

© www.soinside.com 2019 - 2024. All rights reserved.