使用带有 React Router 道具的上下文

Using Contexts that take props with React Router

我有一个跟踪各种服务器信息的应用程序。我有一个 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 路由器为每台服务器设置一个 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

我怀疑这里发生的情况是,当路由路径切换时,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 属性添加为 ServerDataContextProvideruseEffect 挂钩中的依赖项也将清除任何现有的间隔计时器并使用更新后的 [=14= 重新启动它们]道具的价值。

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]);