typescript - 是什么导致 Redux 中更新状态出现 "Delay"?

标签 typescript react-native redux react-redux

我很难理解我在下面的 Redux 和 React native 代码中做错了什么。

我正在尝试创建一个锻炼跟踪应用程序,用户可以在其中输入他们的锻炼进度。我创建了一个“workoutSessionSlice”来跟踪状态。

const initialState: IWorkoutSessionState = {
  currentTrackingEquipment: {
    createdOn: { seconds: 0, nanoseconds: 0 },
    equipmentName: '',
    repetitions: [],
    results: [],
    repetitionIndex: 0,
  },
  hasRunningSession: false,
  isTrackingEquipment: false,
  savedSessionEquipmentRecords: [],
};

export const workoutSessionSlice = createSlice({
  name: 'workoutSession',
  initialState,
  reducers: {
    saveEquipmentRecord: (
      state: any,
      action: PayloadAction<IEquipmentRecord>,
    ) => {
      state.savedSessionEquipmentRecords.push(action.payload);
    },
    addResult: (state: any, action: PayloadAction<IRepResult>) => {
      state.currentTrackingEquipment.results[
        state.currentTrackingEquipment.repetitionIndex
      ] = action.payload;
    },
    updateRepIndex: (state: any, action: PayloadAction<number>) => {
      state.currentTrackingEquipment.repetitionIndex = action.payload;
    },
  },
});

用户使用某件设备,并通过按钮将每次重复的结果添加到状态中。我注意到,当我在该按钮的功能中 console.log 有效负载和状态时,状态存在“延迟”:

const handleAddRep = (success: boolean, nextRepIndex: boolean) => {

    console.log({
      repetitions:
        workOutSession.currentTrackingEquipment.results[
          workOutSession.currentTrackingEquipment.repetitionIndex
        ].repetitions,
      weight: equipmentTracking.wheelPickerValue,
      success,
    });

    dispatch(
      addResult({
        repetitions:
          workOutSession.currentTrackingEquipment.results[
            workOutSession.currentTrackingEquipment.repetitionIndex
          ].repetitions,
        weight: equipmentTracking.wheelPickerValue,
        success,
      }),
    );

    console.log(workOutSession);
  };

控制台:

Object {
  "repetitions": 15,
  "success": true,
  "weight": 100,
}

Object {
  "currentTrackingEquipment": Object {
    "createdOn": Object {
      "nanoseconds": 735000000,
      "seconds": 1671364848,
    },
    "equipmentName": "Bench-press-incline",
    "repetitionIndex": 0,
    "repetitions": Array [
      15,
      12,
      7,
    ],
    "results": Array [
      Object {                  // expected this object to be replaced
        "repetitions": 15,
        "success": false,
        "weight": 0,
      },
      Object {
        "repetitions": 12,
        "success": false,
        "weight": 0,
      },
      Object {
        "repetitions": 7,
        "success": false,
        "weight": 0,
      },
    ],
  },
  "hasRunningSession": true,
  "isTrackingEquipment": true,
  "savedSessionEquipmentRecords": Array [],
}

当我在按钮功能之外手动记录状态时,我确实在数组和对象中看到了正确的数据:

Object {
  "currentTrackingEquipment": Object {
    "createdOn": Object {
      "nanoseconds": 735000000,
      "seconds": 1671364848,
    },
    "equipmentName": "Bench-press-incline",
    "repetitionIndex": 1,
    "repetitions": Array [
      15,
      12,
      7,
    ],
    "results": Array [
      Object {
        "repetitions": 15,
        "success": true,
        "weight": 100,
      },
      Object {
        "repetitions": 12,
        "success": false,
        "weight": 0,
      },
      Object {
        "repetitions": 7,
        "success": false,
        "weight": 0,
      },
    ],
  },
  "hasRunningSession": true,
  "isTrackingEquipment": true,
  "savedSessionEquipmentRecords": Array [],
}

问题是,当我想要保存记录时,也会发生这种“延迟”,导致结果数组中的最后一个对象无法更新。

onPress={() => {
  Alert.alert('Successfully finished rep?', undefined, [
    {
      text: 'Yes',
      onPress: () => {
        if (
          workOutSession.currentTrackingEquipment
            .repetitionIndex ===
          workOutSession.currentTrackingEquipment.results.length - 1
        ) {
          handleAddRep(true, false);  // Should update rep in "currentTrackingEquipment"
          Alert.alert('Finished tracking equipment?', undefined, [
            {
              text: 'Yes',
              onPress: () => {
                handleFinishEquipmentTracking(); // adds current tracking equipment to "savedSessionEquipmentRecords"
              },
            },
            {
              text: 'No, go back',
            },
          ]);
        } else {
          handleAddRep(true, true);
        }
      },
    },
  ]);
}}

我尝试在对象键上设置值,而不是替换整个对象,但这效果不佳。任何帮助将不胜感激!

解决了!感谢弗里

以下是我为使其工作而进行的更改: 我将上面的代码称为“handleFinishEequipmentTracking”,如下所示:

const handleFinishEquipmentTracking = () => {
  dispatch(
    saveEquipmentRecord({
      createdOn: workOutSession.currentTrackingEquipment.createdOn,
      equipmentName: workOutSession.currentTrackingEquipment.equipmentName,
      repetitions: workOutSession.currentTrackingEquipment.repetitions,
      results: workOutSession.currentTrackingEquipment.results,
      repetitionIndex:
        workOutSession.currentTrackingEquipment.repetitionIndex,
    }),
  );
};

正如 Phry 解释的那样,“saveEquipmentRecord”中作为参数给出的对象是一个局部变量,并且当“handleAddRep”更改状态时不会更新。我必须在“saveEquipmentRecord”函数中进行两个简单的更改:

const handleFinishEquipmentTracking = () => {
  dispatch(saveEquipmentRecord());
};

在 reducer 中,我更改了保存的 EquipmentRecords 的数据源是状态本身,而不是局部变量中状态的副本:

来自:

saveEquipmentRecord: (
  state: any,
  action: PayloadAction<IEquipmentRecord>,
) => {
  state.savedSessionEquipmentRecords.push(action.payload);
},

至:

saveEquipmentRecord: (state: any) => {
  state.savedSessionEquipmentRecords.push(state.currentTrackinEquipment);
},

最佳答案

没有“延迟” - 您正在查看永远不会更新的旧(“陈旧”)数据。

请参阅此示例:

let state = { foo: 1 }
const s = state
state = { foo: 2 }
// s is now { foo: 1 } and state is { foo: 2 }

仅仅因为您的状态更新为新值(并且它将是一个全新的对象,因为状态更新是不可变的)并不意味着您的局部变量将会更新 - 它们仍然会指向之前的相同值。

将来,该组件将重新渲染 - 然后 const something = useSelector(...)将重新执行。然后你就有了一个具有相同名称的新变量,并且该新变量将具有新值(但很快又会过时)。

关于typescript - 是什么导致 Redux 中更新状态出现 "Delay"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74841527/

相关文章:

reactjs - 新的 React Context API + LocalStorage + Subscribe(Redux 的替换)

javascript - 为什么 1 扩展 {[Key : string]: never} is false

typescript - 如何从 TypeScript 中的 mocha 导入 "describe"和 "it"?

typescript - 调用超父类(super class)的方法

javascript - 在整个屏幕上获取触摸事件

twitter-bootstrap - 如何通过 prop 打开折叠的 div?

Angular 4 :leave animation not triggering

javascript - Meteor 1.3 中 "inProgress-team/react-native-meteor"的响应式使用

reactjs - 在选项卡导航器中调用堆栈函数会导致应用程序崩溃

javascript - Redux useSelector 过滤对象?