【问题标题】:confused about what I have being non-serializable in redux (redux error)对我在 redux 中不可序列化的内容感到困惑(redux 错误)
【发布时间】:2021-06-05 17:36:28
【问题描述】:

我的 react-native 正在工作,这个页面(屏幕)已经完成并完全正常工作,但由于某种奇怪的原因,现在它开始失败,出现 non-serializablesave_rest_second_input 错误。我正在尝试了解我的代码中不可序列化的内容

错误:

A non-serializable value was detected in the state, in the path: `intervalTimer.timer`. Value:, Timer {
// code
Take a look at the reducer(s) handling this action type: TIMER/SAVE_REST_SECONDS_INPUT.

**reducer 正在处理SAVE_REST_SECONDS_INPUT **

import { TIMER } from '../types.js';

const defaultState = {
  timer: null,
  active: true,
  updated: false,
  numberOfSets: 1,
  currentSet: 1,
  minutesInput: '',
  secondsInput: '',
  restMinutesInput: '',
  restSecondsInput: '',
  view: TIMER.INPUTS_VIEW,
  paused: false,
  rest_time: 0,
  rest_exercise: null
};

const intervalTimer = (state = defaultState, action) => {
  switch (action.type) {
// code
    case TIMER.SAVE_REST_SECONDS_INPUT: {
      return {
        ...state,
        restSecondsInput: action.payload,
      };
    }
//code
  }
};

export default intervalTimer;

它下面的另一个错误:

Error: Invariant failed: A state mutation was detected between dispatches, in the path 'intervalTimer.timer._startTime'.

在我的间隔计时器屏幕中,这是我唯一使用过的startTime

        const optionsActive = {
            startTime: parseInt(minutesInput || '0') * 60 * 1000 + parseInt(secondsInput || '1') * 1000, //how long the timer will be set to
            updateFrequency: 100,
            selfAdjust: true,
            countdown: true,
        };

        const optionsRest = {
            startTime: parseInt(restMinutesInput || '0') * 60 * 1000 + parseInt(restSecondsInput || '1') * 1000,
            updateFrequency: 100,
            selfAdjust: true,
            countdown: true,
        };

redux 商店

const persistConfig = {
  key: 'root',
  storage: AsyncStorage,
  stateReconciler: autoMergeLevel2,
  blacklist: ['intervalTimer', 'creatingWorkout', 'creatingWorkoutPlan']
}

const persistedReducer = persistReducer(persistConfig, rootReducer)
export const store = configureStore({
  reducer: persistedReducer,
  enhancers: [Reactotron.createEnhancer()],
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(expoLogger),
    devTools: process.env.NODE_ENV !== 'production'
})
export const persistor = persistStore(store);

对不起,如果问题是菜鸟。我试图理解为什么这会失败,因为我认为一切都是可序列化的。

编辑:这是它打印出来的Timer 的值

A non-serializable value was detected in the state, in the path: `intervalTimer.timer`. Value:, Timer {
  "_currentTime": 0,
  "_drift": 0,
  "_eventEmitter": EventEmitter {
    "_events": Object {
      "end": [Function anonymous],
      "update": [Function anonymous],
    },
    "_eventsCount": 2,
    "_maxListeners": undefined,
  },
  "_expected": 0,
  "_isPaused": false,
  "_isRunning": false,
  "_startTime": 0,
  "_timeAtStart": 0,
  "animationFrame": false,
  "countdown": true,
  "endTime": null,
  "off": [Function removeEventListener],
  "on": [Function addEventListener],
  "selfAdjust": true,
  "startTime": 5000,
  "updateFrequency": 100,
}, 

【问题讨论】:

    标签: javascript reactjs react-native redux expo


    【解决方案1】:

    第一条错误消息表示state.intervalTimer.timer 不可序列化。作为“可序列化”,我们考虑 JSON.parse(JSON.serialize(value)) 将返回原始值的所有内容,因此基本的东西,如字符串和数字,以及数组和普通对象 - 但不包括类实例。众所周知,这些值会导致中间件(如 redux-persist 和 devtools)出现问题,我们对此提出警告。

    另见Redux Style Guide: Do Not Put Non-Serializable Values in State or Actions

    第二条错误消息是关于在减速器之外改变你的状态的东西,即改变值state.intervalTimer.timer._startTime

    这可能是由类似代码引起的

    const obj = { _startTime: 0 }
    dispatch(action(obj))
    // the reducer would now store the object in state
    // and now you change that same object - outside of the reducer, but changing a reference that is in the store
    obj._startTime = 5
    

    或通过类似代码

    const obj = useSelector(state => state._startTime)
    // and now you change that same object - outside of the reducer, but changing a reference that is in the store
    obj._startTime = 5
    

    【讨论】:

    • 我不敢问这个问题,但是我怎样才能知道这个不可序列化的值在哪里呢?我进入intervalTimer 内部,其中必须有一个timer(我假设基于它的命名方式)。我也用 redux 调试设置对原生调试器做出了反应。感谢您的出色回答,它确实帮助我理解了最终是什么可串行化,我知道我的第二个问题很难回答,但我不知道该怎么问
    • 我不知道,因为你把所有可能设置timer 的代码都放在那里了?
    • 你是对的。我更新了我的问题并包含了代码。我的道歉
    • 您显然在 Redux 中存储了一个 Timer(来自我不知道的任何库,但您可能会这样做)对象。这不属于 Redux,因为计时器不是数据,而 Redux 存储是用于存储数据,仅此而已。 “数据”将是有关计时器何时启动或何时结束的信息,或者是计时器的 ID。但不是计时器本身,具有“开始”方法和“暂停”方法 - 触发其中任何一个都会修改计时器,这反过来又是在 reducer 之外修改 redux 状态 - 在 redux 中是严格禁止的。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-14
    • 1970-01-01
    • 2018-02-25
    • 2016-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多