使用带有 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
属性添加为 ServerDataContextProvider
的 useEffect
挂钩中的依赖项也将清除任何现有的间隔计时器并使用更新后的 [=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]);
我有一个跟踪各种服务器信息的应用程序。我有一个 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
属性添加为 ServerDataContextProvider
的 useEffect
挂钩中的依赖项也将清除任何现有的间隔计时器并使用更新后的 [=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]);