使用 Context API 在 React router v6 路由之间共享状态

yab*_*ugh 5 javascript reactjs react-router react-router-dom react-context

浏览旧教程,React Router v5 似乎支持使用上下文 API 在不同路由之间共享状态,但我找不到 Router v6 的类似用法。

React Router v5 实现我正在尝试做的事情:

const [user, setUser] = useState(null);
 return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about/">About</Link>
            </li>
          </ul>
        </nav>
        <UserContext.Provider value={user,setUser}>
          <Route path="/" exact component={Index} />
          <Route path="/about/" component={About} />
        </UserContext.Provider>
      </div>
    </Router>
  );
Run Code Online (Sandbox Code Playgroud)

然后你可以使用useContext钩子访问状态

const {value, setValue} = useContext(UserContext);
Run Code Online (Sandbox Code Playgroud)

v6 实施

当尝试将此实现与 v6 一起使用(将降级的 v5 组件替换为新的 v6 组件)时,您将遇到错误,因为您只能将<Route>组件作为路由器中的子组件。

是否可以跨 React Router V6 路由与全局上下文存储共享状态?

以下是我在 V6 实现上的尝试:

索引.js

import { BrowserRouter as Router } from "react-router-dom";

ReactDOM.render(
  <Router>
    <App />
  </Router>,
  document.getElementById("root")
);
Run Code Online (Sandbox Code Playgroud)

应用程序.js

const [value, setValue] = useState("initial state");

  return (
    <>
      <Header props={(key, setKey)} />
      <DataContext.Provider value={(value, setValue)}>
        <Route path="/" element={<Dashboard />} />
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/configuration" element={<Configuration />} />
      </DataContext.Provider>
    </>
  );
Run Code Online (Sandbox Code Playgroud)

App.js 不同的方法

  const [value, setValue] = useState("initial state");

  return (
    <DataContext.Provider value={(value, setValue)}>
      <Header props={(key, setKey)} />
      <Routes>
        <Route path="/" element={<Dashboard />} />
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/configuration" element={<Configuration />} />
      </Routes>
    </DataContext.Provider>
  );
}
Run Code Online (Sandbox Code Playgroud)

此解决方案的问题是,当其中一条路由发生更改时,状态仍未全局更新。 例如/dashboard如果我使用setValuethen 更改值,它将反映更改/dashboard,但如果我导航到/configuration或刷新value将恢复到原始value状态,在这种情况下为“初始状态”。App.js(如果我创建一个将使用的函数setValue并将该函数传递给 Provider,这也是效果)

我确信我可以使用 React Redux 来解决这个问题,但它实际上只是我需要在路由之间共享的一两个数据 - 实现所有所需的 redux 样板等似乎有点矫枉过正,而且似乎是一个常见的用例该背景应该支持。

Shu*_*mar 6

它很简单,您需要Router在您的DataProvider.

索引.js

// import { BrowserRouter as Router } from "react-router-dom";

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
Run Code Online (Sandbox Code Playgroud)

应用程序.js

import { BrowserRouter as Router } from "react-router-dom";
// .....
// .....
// .....
 const [value, setValue] = useState("initial state");

  return (
    <DataContext.Provider value={(value, setValue)}>
      <Header props={(key, setKey)} />
      <Router>
      <Routes>
        <Route path="/" element={<Dashboard />} />
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/configuration" element={<Configuration />} />
      </Routes>
      </Router>
    </DataContext.Provider>
  );
}
Run Code Online (Sandbox Code Playgroud)

还要确保您使用Link路由器导航到不同的页面。使用任何其他刷新页面的“a”标签等都会重置context.

  • 如果您想将所有路由包装在 DataContext 中,这很好,但是如果您只想将 Context 包装在某些嵌套路由周围怎么办? (2认同)