Ben*_*ier 4 typescript reactjs react-router-dom
任何大型应用程序都会有可能需要路由器重定向用户的一般上下文。由于RouterProvider只能在根级别使用。如何将它与应用程序上下文一起使用。
例如,ApiContext如果用户无权访问 API,我会重定向到 403 路由/组件。
如何将此上下文包装在 中,而RouterProvider不必在每次路由更改时重新渲染它。换句话说。我怎样才能拥有使用路由器的父上下文?
如果我使用 ,它工作得很好BrowserRouter,但在 v6.8 中卸载之前使用任何类型的提示的唯一方法是使用数据 api 和方法createBrowserRouter。
标题导航也是如此。我不希望我的标头出现在每个路由组件和路由的一部分中。我希望我的标头是静态的,而路由组件是动态的。
// Aplication Context
export const ApiContext = React.createContext({});
export const ApiProvider = memo((p: { children: React.ReactNode; }) => {
const navigate = useNavigate();
const [token, setToken] = useState<string>()
if (!token) {
navigate('/403');
}
const value = useMemo(() => ({}), []);
return (
<ApiContext.Provider value={value}>
{p.children}
</ApiContext.Provider>
);
});
Run Code Online (Sandbox Code Playgroud)
// Index
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
children: [
{
path: "403",
element: <Login />,
},
],
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<ApiProvider>
<Header />
<RouterProvider router={router} />
</ApiProvider>
);
Run Code Online (Sandbox Code Playgroud)
事实上,它是RouterProvider 应用程序的根节点/元素/组件,它只需要在 ReactTree 中比任何需要访问它提供的路由上下文的渲染组件更高。
如果你正在渲染的组件需要访问路由器提供的路由上下文,例如useNavigate,等等,那么它们必然需要在路由器提供者创建的ReactTree下渲染,即路由器组件。
将其移至布局路线ApiProvider上的路由器中。该组件现在还应该渲染嵌套路由以将其内容渲染到其中,而不是prop。ApiProviderOutletelementchildren
该ApiProvider组件也不应该navigate直接在组件主体中作为无意的副作用进行调用。将if (!token)检查和重定向移至useEffect挂钩中,或者仅使用组件呈现重定向Navigate。
例子:
应用上下文
import { Navigate, Outlet } from 'react-router-dom';
export const ApiContext = React.createContext({});
export const ApiProvider = () => {
const [token, setToken] = useState<string>("");
const value = useMemo(() => ({}), []);
if (!token) {
return <Navigate to="/403" replace />;
}
return (
<ApiContext.Provider value={value}>
<Header />
<Outlet />
</ApiContext.Provider>
);
};
Run Code Online (Sandbox Code Playgroud)
指数
const router = createBrowserRouter([
{
element: <ApiProvider />,
children: [
{
path: "/",
element: <Root />,
loader: rootLoader,
children: [
{
path: "team",
element: <Team />,
loader: teamLoader,
},
],
},
],
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<RouterProvider router={router} />
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10811 次 |
| 最近记录: |