【问题标题】:Using Contexts that take props with React Router在 React Router 中使用带有 props 的上下文
【发布时间】:2021-12-29 14:51:51
【问题描述】:

我有一个应用程序正在跟踪有关各种服务器的信息。我有一个 Web 服务器,我可以通过服务器名称查询信息。我为此信息创建了一个上下文,它以服务器名称作为道具并定期更新其数据。见下文;

ServerContext.js

export const ServerDataContext = createContext();

export const ServerDataContextProvider = ({
  children,
  server= "",
}) => {
  const [serverConfig, setServerConfig] = useState({});

  const updateServerData = () => {;
    serverConfigRequest(server).then((res) => {
      setServerConfig((old) => {
        return res;
      });
    });
  };

  useEffect(() => {
    console.log("init");
    updateServerData();
    const updateInterval = setInterval(
      updateServerData,
      serverConfigUpdateFrequency * 1000
    );

    return () => {
      clearInterval(updateInterval);
    };
  }, []);

  return (
    <ServerDataContext.Provider
      value={{
        serverConfig,
      }}
    >
      {children}
    </ServerDataContext.Provider>
  );
};

在我的 App.js 中,我使用 react router to 为每个服务器设置一个 StatusPage。它看起来像这样:

App.js

function App() {
  return (
    <Router>
      <div className="app">
        <Header />
        <Routes>
          <Route exact path="/" element={<div>Overview</div>} />
          <Route
            exact
            path="/server_1"
            element={
              <ServerDataContextProvider server="server_1">
                <StatusPage server="server_1" />
              </ServerDataContextProvider>
            }
          />
          <Route
            exact
            path="/server_2"
            element={
              <ServerDataContextProvider server="server_2">
                <StatusPage server="server_2" />
              </ServerDataContextProvider>
            }
          />
        </Routes>
        <Footer />
      </div>
    </Router>
  );
}

我有按钮可以转到标题中的每个页面。当我加载第一个服务器状态页面时,页面更新得非常好。我看到服务器上的请求以正确的时间间隔传入 server_1。然后我导航到 server_2 我在浏览器搜索栏中看到路由更新,但页面上的内容没有。我在我的网络服务器上收到的请求仍然以相同的时间间隔针对 server_1,就好像我没有切换页面一样。如果我仍然在 server_2 的端点刷新页面,则页面上的内容将为 server_2 正确更新,但这次 server_1 也会出现同样的问题。

我是否不恰当地使用上下文?我认为问题在于我如何构建应用程序但不确定。任何建议表示赞赏。

编辑: https://codesandbox.io/s/admiring-haibt-vxm62?file=/src/ServerContext.js

【问题讨论】:

  • 您的代码 sn-p 中似乎有点不对劲。对于路由渲染路径“/server_2”,您似乎使用了完全不同的上下文提供程序ServerDataContextProviderhardwareString,并且与结束标记不匹配。这只是拼写错误还是复制/粘贴错误?认为您可以创建一个 running 代码框演示来重现我们可以实时检查和调试的双重上下文问题(模拟serverConfigRequest 函数 OFC)?
  • 嗨 Drew,这是我已修复的复制粘贴错误。我现在将尝试组装一个沙盒。
  • 我在这里做了一个代码沙箱(codesandbox.io/s/admiring-haibt-vxm62?file=/src/…)。让我知道您是否可以出于某种原因访问它。它的配置方式是 server_1 应始终为绿色,server_2 应始终为红色。您会发现,如果您转到 server_1,它将是绿色的,但是当您导航到 2 时,它将保持绿色,直到您刷新页面。它显示了我遇到的问题。谢谢。

标签: javascript reactjs react-hooks react-router-dom react-context


【解决方案1】:

我怀疑这里发生的情况是,当路由路径切换时,React 树实际上是相同的,并且没有安装服务器 2 的上下文提供程序。 我当然没有看到它安装,即使安装了useEffect,并且仍在提供服务器 1 上下文值。

在App 中为每个提供者添加一个 React 键确实可以解决问题,并通知 React 这实际上是两个不同的组件,它必须使用给定的 props 重新安装提供者并重新实例化上下文值。

<Routes>
  <Route path="/" element={<div>Overview</div>} />
  <Route
    path="/server_1"
    element={
      <ServerDataContextProvider key="server_1" server="server_1">
        <StatusPage server="server_1" />
      </ServerDataContextProvider>
    }
  />
  <Route
    path="/server_2"
    element={
      <ServerDataContextProvider key="server_2" server="server_2">
        <StatusPage server="server_2" />
      </ServerDataContextProvider>
    }
  />
</Routes>

或者,将server 属性添加为ServerDataContextProvider 的useEffect 挂钩中的依赖项也将清除任何现有的间隔计时器并使用更新的server 属性值重新启动它们。

useEffect(() => {
  // moved into effect callback to remove as dependency
  const updateServerData = () => {
    setServerConfig((old) => {
      return { server: server == "server_1" ? "G" : "R" };
    });
  };

  console.log("init");
  updateServerData();
  const updateInterval = setInterval(updateServerData, 5 * 1000);

  return () => {
    clearInterval(updateInterval);
  };
}, [server]);

【讨论】:

  • 这似乎成功了。感谢您提供详细的解释。它应该可以帮助我将来避免这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-03
  • 2016-04-19
  • 2021-12-29
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 2021-04-02
相关资源
最近更新 更多