【问题标题】:state resets when transitioning route(page)转换路由(页面)时状态重置
【发布时间】:2021-01-12 06:18:01
【问题描述】:

我在CodeSandbox 中重现了问题

https://codesandbox.io/s/competent-newton-up21l?file=/pages/index.js

我有两条路线(页面)

  • /
  • /car/info

还有两个组件

  • 标题
  • 汽车输入法

我使用上下文来维护状态并将其传递给两个页面。

当我在路由 /car/info 中并且我使用 input 更改状态时,更新的状态将显示在同一路由(页面)的 Header 组件中。

但是当我转到/ route(page) 时,状态没有更新。我使用反应开发工具进行了检查,并且上下文没有更新的值。

即使我回到 /car/info ,更新的状态也不存在。一旦我从/car/info 转换到/,状态就会回到初始状态。

在沙盒上重新创建相同的步骤

  1. 点击“去添加汽车”
  2. 在输入框中输入车名并点击添加
  3. 点击“回家”

现在您可以看到您添加的汽车不存在。

更新:正如下面的答案所指出的,我正在更新 localState 。 我修复了代码以使用全局状态,但问题仍然存在。

新沙盒:https://codesandbox.io/s/inspiring-pond-mp134?file=/context/cars-context.js

【问题讨论】:

    标签: reactjs next.js react-context


    【解决方案1】:

    首先,您在添加汽车时在哪里更新状态。

      function handleSubmit(e) {
        e.preventDefault();
        let car = e.target.elements["car"].value;
        setCars((prevState) => {
          return [...prevState, car];
        });
      }
    

    我从您的仓库复制的上述代码,仅将新添加的汽车更新为本地状态。这就是它在上下文中不可用的原因。您已经创建了一个全局上下文,但没有使用它。

    你要做的是,

    在您的 carInput 类中访问上下文

    const [initialState, dispatch] = useCarContext();
    
     
    function handleSubmit(e) {
            e.preventDefault();
            let car = e.target.elements["car"].value;
           // Instead of updating to local state, 
          //upadate your global context using dispatch
           // in dispatch pass actionType and the value
           dispatch({ type: 'updateNewCar', value: car });
          }
    

    还附上示例上下文实现(您可以根据自己的用例进行更改)

    import React, { createContext, useContext, useReducer } from "react";
    
    export const initCarContext = () => {
      return {
        initialState: {
          cars: []
        },
        reducer: function (state, { type, value }) {
          switch (type) {
            case 'updateNewCar':
              state.cars.push(value)
              return { ...state };
    
            default:
              return state;
          }
        }
      };
    };
    
    export const StateContext = createContext();
    export const CarStateProvider = ({ reducer, initialState, children }) => (
      <StateContext.Provider value={useReducer(reducer, initialState)}>
        {children}
      </StateContext.Provider>
    );
    export const useCarContext = () => useContext(StateContext);
    

    https://kentcdodds.com/blog/how-to-use-react-context-effectively/

    【讨论】:

    【解决方案2】:

    在 next.js 中进行页面转换时,上下文会被卸载。

    因此,在 __app.js 页面中包装上下文提供程序可确保在进行转换时它不会被卸载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-28
      • 2021-04-13
      • 1970-01-01
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      相关资源
      最近更新 更多