我刚刚react-router从 v3 更换到 v4。 但我不确定如何以编程方式在 a 的成员函数中导航Component。即在处理一些数据后handleClick()我想导航到的功能。/path/some/where我曾经这样做过:
react-router
Component
handleClick()
/path/some/where
import { browserHistory } from 'react-router' browserHistory.push('/path/some/where')
但是我在 v4 中找不到这样的接口。 如何使用 v4 进行导航?
如果您的目标是浏览器环境,则需要使用react-router-dom包,而不是react-router. 它们遵循与 React 相同的方法,以便将核心 ( react) 和平台特定代码 ( react-dom, react-native) 分开,但您不需要安装两个单独的包,因此环境包包含所有内容你需要。您可以将其添加到您的项目中:
react-router-dom
react
react-dom
react-native
yarn add react-router-dom
要么
npm i react-router-dom
您需要做的第一件事是提供一个<BrowserRouter>作为应用程序中最顶层的父组件。<BrowserRouter>使用 HTML5 historyAPI 并为您管理它,因此您不必担心自己实例化它并将其<BrowserRouter>作为道具传递给组件(正如您在以前的版本中需要做的那样)。
<BrowserRouter>
history
在 V4 中,为了以编程方式导航,您需要访问history通过 React 可用的对象,context只要您有一个<BrowserRouter> 提供程序 组件作为应用程序中最顶层的父组件。该库通过上下文公开router对象,该对象本身history作为属性包含。该history界面提供了多种导航方法,例如push、replace和goBack等。您可以在此处查看属性和方法的完整列表。
context
router
push
replace
goBack
如果您在应用程序中使用 redux 或 mobx 作为您的状态管理库,您可能会遇到组件应该是位置感知但在触发 URL 更新后不会重新渲染的问题
发生这种情况是因为使用上下文模型react-router传递给组件。location
location
connect 和 observer 都创建组件,其 shouldComponentUpdate 方法对其当前 props 和下一个 props 进行浅比较。这些组件只会在至少一个道具发生变化时重新渲染。这意味着为了确保它们在位置更改时更新,需要为它们提供一个在位置更改时更改的道具。
解决此问题的两种方法是:
<Route />
<Route>
withRouter``location
除此之外,有四种以编程方式导航的方法,按推荐排序:
它提倡声明式风格。在 v4 之前,<Route />组件被放置在组件层次结构的顶部,必须事先考虑您的路由结构。但是,现在您可以在树中的 任何位置*<Route>拥有组件,从而允许您更好地控制根据 URL 有条件地呈现。将,和as props 注入到您的组件中。导航方法(例如, , …)可用作对象的属性。 *Route``match``location``history``push``replace``goBack``history
Route``match``location``history``push``replace``goBack``history
有 3 种方法可以使用 、 、 或道具来渲染某些东西Route,component但render不要children在同一个 . 中使用多个Route。选择取决于用例,但基本上前两个选项只会在path与 url 位置匹配时呈现您的组件,而children无论路径是否与位置匹配,都会呈现组件(对于基于 URL 调整 UI 很有用匹配)。
Route
component
render
children
path
如果您想自定义组件渲染输出 ,您需要将组件包装在一个函数中并使用该选项,以便将您想要的任何其他道具传递给您的组件,render除了和。一个例子来说明:match``location``history
match``location``history
import { BrowserRouter as Router } from 'react-router-dom' const ButtonToNavigate = ({ title, history }) => ( <button type="button" onClick={() => history.push('/my-new-location')} > {title} </button> ); const SomeComponent = () => ( <Route path="/" render={(props) => <ButtonToNavigate {...props} title="Navigate elsewhere" />} /> ) const App = () => ( <Router> <SomeComponent /> // Notice how in v4 we can have any other component interleaved <AnotherComponent /> </Router> );
withRouter
这个高阶组件将注入与Route. 但是,它具有每个文件只能有 1 个 HoC 的限制。
import { withRouter } from 'react-router-dom' const ButtonToNavigate = ({ history }) => ( <button type="button" onClick={() => history.push('/my-new-location')} > Navigate </button> ); ButtonToNavigate.propTypes = { history: React.PropTypes.shape({ push: React.PropTypes.func.isRequired, }), }; export default withRouter(ButtonToNavigate);
Redirect
渲染 a<Redirect>将导航到一个新位置。但请记住, 默认情况下 ,当前位置会被新位置替换,例如服务器端重定向 (HTTP 3xx)。新位置由toprop 提供,可以是字符串(要重定向到的 URL)或location对象。如果您想 将新条目推送到历史记录 中,请同时传递一个push道具并将其设置为true
<Redirect>
to
true
<Redirect to="/your-new-location" push />
有点气馁,因为context仍然是一个实验性 API,它可能会在未来的 React 版本中中断/更改
const ButtonToNavigate = (props, context) => ( <button type="button" onClick={() => context.router.history.push('/my-new-location')} > Navigate to a new location </button> ); ButtonToNavigate.contextTypes = { router: React.PropTypes.shape({ history: React.PropTypes.object.isRequired, }), };
毋庸置疑,还有其他路由器组件旨在用于非浏览器生态系统,例如<NativeRouter>复制 内存中 的导航堆栈并以 React Native 平台为目标,可通过react-router-native包获得。
<NativeRouter>
react-router-native