Reactjs usereducer-仅将特定状态持久化到会话存储?

Reactjs usereducer-仅将特定状态持久化到会话存储?,reactjs,use-reducer,Reactjs,Use Reducer,我有一个动词变位测验。您可以将所需共轭的过滤器选项发送到后端,然后它会发回必要的信息。在我的测验页面中,我有一个usereducer,它将管理所有这些状态。我希望将共轭数据以及当前共轭(所以是当前问题)索引持久化到会话存储中 但是,我不希望错误状态、用户输入、应重定向变量(如果用户未指定任何筛选器选项,则将重定向)等数据被持久化,因为如果刷新页面,您不希望错误消息持久化,或者至少我觉得这不是我想要的 关键是,这些状态不能在不同的还原器中分离,因为我想在同一个操作中更改一些局部状态和持久化状态 我

我有一个动词变位测验。您可以将所需共轭的过滤器选项发送到后端,然后它会发回必要的信息。在我的测验页面中,我有一个usereducer,它将管理所有这些状态。我希望将共轭数据以及当前共轭(所以是当前问题)索引持久化到会话存储中

但是,我不希望错误状态、用户输入、应重定向变量(如果用户未指定任何筛选器选项,则将重定向)等数据被持久化,因为如果刷新页面,您不希望错误消息持久化,或者至少我觉得这不是我想要的

关键是,这些状态不能在不同的还原器中分离,因为我想在同一个操作中更改一些局部状态和持久化状态

我提出了一个非常简单的解决方案,就是将我想要持久化的状态放在一个名为persistend的对象中:

{
    persisted: {
       conjugations: [...],
       currentConjugationIndex: 2,
       numOfCorrectAnswers: 1,
       numOfIncorrectAnswers: 3
    },

    userAnswer: "habló",
    error: ""
    ...
}

这意味着所有这些状态都可以在一个reducer中,然后只是持久化那个持久化的对象,而不是整个对象。我只是觉得我没有看到其他人有这个问题,这让我怀疑我是否应该做些别的事情。意见

编辑:

到目前为止,我的代码是:

const useQuizReducer = () => {
    const persistedState = JSON.parse(sessionStorage.getItem("quiz"));

    const [state, dispatch] = useImmerReducer(
        reducer,
        persistedState 
            ? {...initialStates, persisted: persistedState} 
            : initialStates
    );

    useEffect(() => {
        sessionStorage.setItem("quiz", JSON.stringify(state.persisted));
    }, [state.persisted])

    const {persisted, ...rest} = state;

    return [{...persisted, ...rest}, dispatch];
}


你在你的报告中混淆了不同的关注点。我建议你把它们分开。这通常会使代码更加清晰,并且(作为奖励)减少了在复杂的丛林中隐藏bug的机会

  • 第一个问题:客户端运行时状态
  • 第二个问题:页面重新加载之间的状态持久性
您有两个不同的关注点:根据经验,您添加了两个不同的代码部分,每个关注点一个。 下面是一个如何做到这一点的想法:

// the reducer only handles your first concern
const [state, dispatch] = useReducer(reducer, emptyInitialState, tryReadSessionStorage);

// this handles your second concern
useEffect(() => tryUpdateSessionStorage(state), [state]);

// e.g. in some other file
const tryUpdateSessionStorage = ({
  conjugations,
  currentConjugationIndex,
  numOfCorrectAnswers,
  numOfIncorrectAnswers,
}) => {
  try {
    sessionStorage.setItem("quiz", JSON.stringify({
      conjugations,
      currentConjugationIndex,
      numOfCorrectAnswers,
      numOfIncorrectAnswers,
    }));
  } catch (exception) {}
}

const tryReadSessionStorage = (emptyInitialState) => {
  let persistedState;
  try {
    persistedState = JSON.parse(sessionStorage.getItem("quiz"));
  } catch (exception) {}
  return { ...emptyInitialState, ...persistedState };
}


我编辑了我的问题,如果我错了,请纠正我,但这不是我已经在做的吗?嗯,从你问题的第一个版本来看,这并不清楚。我仍然不明白为什么需要引入人工的
持久化的
对象。并且您可能希望利用延迟初始化(useReducer的第三个参数)在第一次渲染时只检查本地存储