如何将上下文 api 与反应路由器 v4 一起使用?
Posted
技术标签:
【中文标题】如何将上下文 api 与反应路由器 v4 一起使用?【英文标题】:How to use context api with react router v4? 【发布时间】:2018-10-13 19:39:04 【问题描述】:我正在我的应用程序上尝试使用 React 16.3 中的新上下文 API 进行一些测试,但我不明白为什么我的重定向永远不起作用。
<ContextA>
<Switch>
<Route exact path='/route1' component= Component1 />
<ContextB>
<Route exact path='/route2' component= Component2 />
<Route exact path='/route3' component= Component3 />
</ContextB>
<Redirect from='/' to='/route1' />
</Switch>
</ContextA>
我不想让我的 ContextB 可用于所有路线,只有 2 和 3 条。我该怎么做?
【问题讨论】:
【参考方案1】:看起来<Switch>
应该只有<Route>
和<Redirect >
组件作为直接子级。 (source)
我想这就是为什么你的Redirect
不能工作的原因,因为你使用ContextB
作为Switch
孩子。
最简单但重复的解决方案可能是将您的 ContextB
作为您想要的每个 <Route>
的子代:
注意:这些解决方案假设您为 Context 组件分配了默认值,如下所示:
const MyContext = React.createContext(defaultValue);
<Route exact path='/route2'>
<ContextB.Provider>
<Component1 />
</ContextB.Provider>
</Route>
您甚至可以为此创建一个ContextRoute
组件:
import React from 'react';
import Route from 'react-router-dom';
const ContextRoute = ( contextComponent, component, ...rest ) =>
const Provider = contextComponent;
const Component = component;
return (
<Route ...rest>
<Provider>
<Component />
</Provider>
</Route>
);
;
export default ContextRoute;
然后将其用作Route:
<ContextA>
<Switch>
<Route exact path='/route1' component= Component1 />
<ContextRoute exact path='/route2' contextComponent=ContextB component= Component2 />
<ContextRoute exact path='/route3' contextComponent=ContextB component= Component3 />
<Redirect from='/' to='/route1' />
</Switch>
</ContextA>
通过此解决方案,您可以在嵌套组件中将上下文与渲染道具一起使用:
return (
<ContextB.Consumer>
value => <div>value</div>
</ContextB.Consumer>
);
但我们可以想象更多的解决方案,例如 HOC,将上下文值直接传递给路由组件道具等...
【讨论】:
成功了,非常感谢!现在我可以更好地理解架构了。 似乎上下文 B 的状态会丢失,但是如果您从 /route2 或 /route3 转到 /route1。似乎通常最好将根放在某个地方,然后在需要它的那些组件中抓取它? @jones 我同意你的做法,但我想这取决于每个应用的目标。 阅读下面的答案,了解为什么这种方法不能真正按预期工作:***.com/a/61824692/4470169【参考方案2】:作为对其他人的警告,接受的答案并不真正起作用,正如您对原始(非工作)概念所期望的那样:
// This comes from the original question (doesn't work as-is!)
<ContextA>
<Switch>
<Route exact path='/route1' component= Component1 />
<ContextB>
<Route exact path='/route2' component= Component2 />
<Route exact path='/route3' component= Component3 />
</ContextB>
<Redirect from='/' to='/route1' />
</Switch>
</ContextA>
在那里,/route2
和 /route3
共享一个上下文,期望应该是:
-
在路由转换之间保持状态。
如果
Component2
或 Component3
更新上下文,则更改应反映给另一个。
对于公认的解决方案,以上都不是真的。
【讨论】:
你说得对,很好。即使您的答案不是一个真正的(也许在已接受的答案中进行评论或编辑会更合适?)。使其工作的一种方法是将 ContextB 提供程序提升到 Switch 组件的上方,并在路线 2 和 3 上使用消费者。我会在有时间时尝试更新答案 我仍在寻找解决方案,但还没有弄清楚。 @Nenu 我对你关于提升上下文提供者的理论感兴趣——你解决过这个问题吗?【参考方案3】:在路由中使用渲染方法。这将解决您的问题,就像我在我的应用程序中所做的那样。
<Route
path="/"
render=(props) => (
<ContextB>
<Component2 ...props />
</ContextB>
)
/>
【讨论】:
【参考方案4】:感谢您的帮助,我在商店环境中使用了它并且有效! (createContext 和 useReducer)
import React, createContext, useReducer from "react";
import Reducer from './reducer.js'
const initialState =
/* */
;
const Store = (children) =>
const [state, dispatch] = useReducer(Reducer, initialState);
return (
<Context.Provider value=[state, dispatch]>
children
</Context.Provider>
)
;
export const Context = createContext(initialState);
export default Store;
/* 在 App.js*/
const App = () =>
return (
<BrowserRouter>
<Switch>
<Route exact path="/" render= (props)=> <Store> <Home ...props /> </Store> />
<Route exact path="/about" render= (props)=> <Store> <About ...props /> </Store> />
<Route exact path="/login" render= (props)=> <Store> <Login ...props /> </Store> />
</Switch>
</BrowserRouter>
);
;
【讨论】:
【参考方案5】:简单的解决方案:
<ContextA>
<Switch>
<Route exact path='/' render= () => <Redirect to='/route1' /> />
<Route path='/route1' component= Component1 />
</Switch>
<ContextB>
<Switch>
<Route path='/route2' component= Component2 />
<Route path='/route3' component= Component3 />
</Switch>
</ContextB>
</ContextA>
【讨论】:
@impulsgraw 会的。您只需在路由声明底部的 switch 包装器中声明错误路由处理程序。 不,不会的。如果有多个交换机,我应该在哪个交换机中包含错误路由,这样路由器就不会一直显示它? 由于 Switch 包装器是嵌套的,因此您必须有条件地呈现您的错误路由处理程序。您可以定义一个自定义函数,循环遍历所有静态路径并返回一个布尔值。如果未找到匹配项,则使用它有条件地呈现您的错误路由处理程序。即 ``` !isMatch() &&以上是关于如何将上下文 api 与反应路由器 v4 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
无法让 Paypal 在上下文中 checkout.js v4 与 REST API 一起使用
如何使反应路由器与静态资产、html5 模式、历史 API 和嵌套路由一起工作?
如何将 React.createContext() 与反应路由器一起使用?
如何将 Github API v4 (graphql) 与 javascript XMLHttpRequest 一起使用