![](/img/trans.png)
[英]Router context undefined with BrowserRouter in react-router-dom v5
[英]React Router V5 best way to use context variable in route
在我的应用程序中,我定义了我的路线,如下所示:
<BrowserRouter>
<Header />
<div className="App">
<Switch>
<Route exact path="/">
<Redirect to="/home" />
</Route>
<Route exact path={["/home", "/"]} component={Home} />
<Route path="/account/:id" render={(props: RouteComponentProps<any>) => <Account {...props} />} />
<Route component={NotFound} />
</Switch>
</div>
</BrowserRouter>
我想知道的是,这可能很棘手,如果我希望我的路线有一个来自我的上下文的前缀,即变量,我将如何做到这一点,但扭曲的是变量来自 api 响应?
那么如果我想要路由/contextVariable/home
但contextVariable
来自 api 响应并存储在上下文值中,我知道如何将该变量带入组件但路由将如何处理它,即不是/undefined/home
作为响应是否需要在插入路由之前完成?
有任何想法吗?
我曾经做过一个有类似要求的项目。 在那里,我没有声明动态路由,而是从 state 获取了一个路由数组,该数组是一个 object 数组,包含组件、路径和一些其他参数。 默认情况下,我添加了初始登录页面和未找到页面:
const [routes, setRoutes] = React.useState([
{
component: HomeComponent,
path: '/',
},
{
component: NoMatchPage,
path: '*',
}
])
然后我在 useEffect 块中有请求,它将像这样更新这个 state:
React.useEffect(()=>{
// call api()
const oldRoutes = routes;
const noMatchPage = oldRoutes.pop();
const newRoutes = [...oldRoutes,
responseFromApi.map(
routeItem =>
({
component: ComponentName,
path: routeItem.path
})
), noMatchPage]
setRoutes(newRoutes)
},[])
抱歉,我忘记了主要部分,这是 Route 渲染的方式:
<Switch>
{
routes.map(routeItem =>
<Route path={routeItem.path} component={routeItem.component} />
)
}
</Switch>
此外,如果您想避免 useEffect 中的额外代码,您可以简单地执行以下操作:
React.useEffect(()=>{
// call api()
setRoutes(responseFromApi.map(
routeItem =>
({
component: ComponentName,
path: routeItem.path
})
))
},[])
接着
<Switch>
<Route exact path={["/home", "/"]} component={Home} />
{
routes.map(routeItem =>
<Route path={routeItem.path} component={routeItem.component} />
)
}
<Route component={NotFound} />
</Switch>
如果您想使用 React Context 执行此操作,那么这是我建议的模式。 创建一个包含 API 逻辑的 React 上下文,以获取“基本路径”并将其公开给消费者。 消费者将采用提供的“基本路径”值并将其添加到所有链接目标和路由路径。
例子:
BasePathProvider
import { createContext, useContext } from "react";
const BasePath = createContext({
basepath: ""
});
const BasePathProvider = ({ children }) => {
... logic to fetch basepath ...
return (
<BasePath.Provider value={{ basepath }}>
{children}
</BasePath.Provider>
);
};
const useBasePath = () => useContext(BasePath);
Header
const Header = () => {
const { basepath } = useBasePath();
return (
...
<Link to={`${basepath}/`}>Home</Link>
<Link to={`${basepath}/account/${/* some id value */}`}>
Account
</Link>
...
);
};
应用程序
function App() {
return (
<div className="App">
<Header />
<BasePath.Consumer>
{({ basepath }) => (
<Switch>
<Redirect from={`${basepath}/`} exact to={`${basepath}/home`} />
<Route path={`${basepath}/home`} component={Home} />
<Route path={`${basepath}/account/:id`} component={Account} />
<Route component={NotFound} />
</Switch>
)}
</BasePath.Consumer>
</div>
);
}
index.js
import { BrowserRouter as Router } from "react-router-dom";
import BasePathProvider from "../path/to/BasePathProvider";
...
<Router>
<BasePathProvider>
<App />
</BasePathProvider>
</Router>
注意:您可能还希望/需要实现“加载” state 以有条件地渲染BasePathProvider
组件的children
组件,直到获取基本basepath
值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.