通过使用react-router
我可以使用Link
元素创建由React Router本机处理的链接。
我在内部看到它的呼唤this.context.transitionTo(...)
。
我想导航。不是来自链接,而是来自下拉菜单(例如)。如何在代码中执行此操作?什么this.context
啊
我看到了Navigation
mixin,但是如果没有我可以这样做mixins
吗?
通过使用react-router
我可以使用Link
元素创建由React Router本机处理的链接。
我在内部看到它的呼唤this.context.transitionTo(...)
。
我想导航。不是来自链接,而是来自下拉菜单(例如)。如何在代码中执行此操作?什么this.context
啊
我看到了Navigation
mixin,但是如果没有我可以这样做mixins
吗?
Answers:
带有钩子的React Router v5.1.0
useHistory
如果您使用React> 16.8.0和功能组件,则React Router> 5.1.0中会有一个新的钩子。
import { useHistory } from "react-router-dom";
function HomeButton() {
const history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
反应路由器v4
使用React Router v4,您可以采用三种方法在组件内进行编程路由。
withRouter
高阶组件。<Route>
context
。React Router主要是history
库的包装器。history
通过浏览window.history
器和哈希历史记录为您处理与浏览器的交互。它还提供了内存历史记录,这对于没有全局历史记录的环境很有用。这在移动应用程序开发(react-native
)和使用Node进行单元测试中特别有用。
一个history
实例有用于导航两种方法:push
和replace
。如果您将history
视为已访问位置的数组,push
则将在该位置添加一个新位置,并用新位置replace
替换该数组中的当前位置。通常,您将push
在导航时使用该方法。
在早期版本的阵营路由器,你必须创建自己的history
实例,但在第4版的<BrowserRouter>
,<HashRouter>
和<MemoryRouter>
组件将创建一个浏览器,哈希和内存的实例为您服务。React Router history
通过router
对象下的上下文使与路由器关联的实例的属性和方法可用。
withRouter
高阶成分的withRouter
高次成分将注入的history
对象作为所述部件的支柱。这样一来,您无需处理即可访问push
和replace
方法context
。
import { withRouter } from 'react-router-dom'
// this also works with react-router-native
const Button = withRouter(({ history }) => (
<button
type='button'
onClick={() => { history.push('/new-location') }}
>
Click Me!
</button>
))
<Route>
该<Route>
组件不仅用于匹配位置。您可以渲染无路径的路线,它将始终与当前位置匹配。该<Route>
组件传递与相同的道具withRouter
,因此您将能够history
通过history
道具访问方法。
import { Route } from 'react-router-dom'
const Button = () => (
<Route render={({ history}) => (
<button
type='button'
onClick={() => { history.push('/new-location') }}
>
Click Me!
</button>
)} />
)
但是你可能不应该
最后一个选项是仅在您对使用React的上下文模型感到满意时才应使用的选项(React的Context API从v16开始是稳定的)。
const Button = (props, context) => (
<button
type='button'
onClick={() => {
// context.history.push === history.push
context.history.push('/new-location')
}}
>
Click Me!
</button>
)
// you need to specify the context type so that it
// is available within the component
Button.contextTypes = {
history: React.PropTypes.shape({
push: React.PropTypes.func.isRequired
})
}
1和2是最简单的实现方法,因此对于大多数用例来说,它们是最好的选择。
withRouter
而不是history
遍历所有组件?我需要花更多的时间阅读文档……
history.push('/new-location')
不将该行为附加到Button或其他DOM元素的情况下直接运行?
Unexpected use of 'history' no-restricted-globals
context
从反应16开始不再是实验性的
React-Router 5.1.0+答案(使用钩子和React> 16.8)
您可以useHistory
在功能组件上使用新的钩子,并以编程方式导航:
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
// use history.push('/some/path') here
};
React-Router 4.0.0+答案
在4.0及更高版本中,将历史记录用作组件的支持。
class Example extends React.Component {
// use `this.props.history.push('/some/path')` here
};
注意:如果您的组件不是由呈现的,则this.props.history不存在<Route>
。您应该使用<Route path="..." component={YourComponent}/>
YourComponent中的this.props.history
React-Router 3.0.0+答案
在3.0及更高版本中,将路由器用作组件的支持。
class Example extends React.Component {
// use `this.props.router.push('/some/path')` here
};
React-Router 2.4.0+答案
在2.4及更高版本中,使用高阶组件将路由器作为组件的道具。
import { withRouter } from 'react-router';
class Example extends React.Component {
// use `this.props.router.push('/some/path')` here
};
// Export the decorated class
var DecoratedExample = withRouter(Example);
// PropTypes
Example.propTypes = {
router: React.PropTypes.shape({
push: React.PropTypes.func.isRequired
}).isRequired
};
React-Router 2.0.0+答案
该版本与1.x向后兼容,因此不需要升级指南。仅通过示例就足够了。
也就是说,如果您希望切换到新模式,则路由器内有一个browserHistory模块,您可以通过该模块访问
import { browserHistory } from 'react-router'
现在您可以访问浏览器历史记录,因此您可以执行推,替换等操作,例如:
browserHistory.push('/some/path')
React-Router 1.xx答案
我不会介绍升级细节。您可以在《升级指南》中阅读有关内容
关于此问题的主要更改是从导航混合到历史的更改。现在,它使用浏览器的historyAPI更改路由,因此我们pushState()
将从现在开始使用。
这是使用Mixin的示例:
var Example = React.createClass({
mixins: [ History ],
navigateToHelpPage () {
this.history.pushState(null, `/help`);
}
})
请注意,这History
来自球拍/历史记录项目。不是来自React-Router本身。
如果由于某种原因(也许由于ES6类)不想使用Mixin,则可以从访问从路由器获得的历史记录this.props.history
。仅路由器提供的组件可以访问它。因此,如果要在任何子组件中使用它,则需要通过将其作为属性向下传递props
。
您可以在其1.0.x文档中了解有关新版本的更多信息。
它建议获取参考history = createHistory()
并进行引用replaceState
。
React-Router 0.13.x答案
我遇到了同样的问题,只能使用react-router附带的Navigation mixin找到解决方案。
这是我做的
import React from 'react';
import {Navigation} from 'react-router';
let Authentication = React.createClass({
mixins: [Navigation],
handleClick(e) {
e.preventDefault();
this.transitionTo('/');
},
render(){
return (<div onClick={this.handleClick}>Click me!</div>);
}
});
我可以拨打电话transitionTo()
而无需访问.context
或者您可以尝试精美的ES6 class
import React from 'react';
export default class Authentication extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
this.context.router.transitionTo('/');
}
render(){
return (<div onClick={this.handleClick}>Click me!</div>);
}
}
Authentication.contextTypes = {
router: React.PropTypes.func.isRequired
};
React-Router-Redux
注:如果您使用的终极版,有一个名为另一个项目 ReactRouter,终极版,为您提供终极版绑定ReactRouter,有些使用了同样的方法 做出反应,终极版呢
React-Router-Redux有几种可用的方法,这些方法允许从动作创建者内部进行简单导航。这些对于在React Native中具有现有架构的人特别有用,并且他们希望以最小的模板开销在React Web中使用相同的模式。
探索以下方法:
push(location)
replace(location)
go(number)
goBack()
goForward()
这是Redux-Thunk的用法示例:
./actioncreators.js
import { goBack } from 'react-router-redux'
export const onBackPress = () => (dispatch) => dispatch(goBack())
./viewcomponent.js
<button
disabled={submitting}
className="cancel_button"
onClick={(e) => {
e.preventDefault()
this.props.onBackPress()
}}
>
CANCEL
</button>
v2.4.0
但是提到的方法对我不起作用,我的应用程序完全无法渲染,控制台输出:Uncaught TypeError: (0 , _reactRouter.withRouter) is not a function
这是指向我的SO帖子的链接:stackoverflow.com/questions/37306166/…–
2.6.0
。
3.0.x
吗?许多人似乎使用这种context
方式。
this.props.history
如果您的组件不是由呈现的,则@ NicolasS.Xu 不存在<Route>
。您应该使用<Route path="..." component={YourComponent}/>
有this.props.history
在YourComponent
。
React-路由器v2
对于最新版本(v2.0.0-rc5
),推荐的导航方法是直接推入历史单例。您可以在Components doc之外的导航中看到这一点。
相关摘录:
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
如果使用较新的react-router API,则需要在组件内部使用history
from this.props
,因此:
this.props.history.push('/some/path');
它还提供了功能,pushState
但已记录的警告已弃用该功能。
如果使用react-router-redux
,它提供了push
可以像这样分派的功能:
import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));
但是,这只能用于更改URL,而不能实际导航到页面。
import { browserHistory } from './react-router'
,而是使用创建历史记录import createBrowserHistory from 'history/lib/createBrowserHistory'
。稍后,您可以history
从组件props中访问:this.props.history('/some/path')
var browserHistory = require('react-router').browserHistory; browserHistory.goBack();
push
仅更改URL,实际上不更改页面。两者都做,进口browserHistory
的react-router
和使用browserHistory.push('/my-cool-path')
。不幸的是,这不是很容易找到。github.com/reactjs/react-router/blob/master/docs/guides/...
react-router
v4中进行程序化导航的
这里是你如何做到这一点react-router v2.0.0
与ES6。react-router
已经摆脱了mixin。
import React from 'react';
export default class MyComponent extends React.Component {
navigateToPage = () => {
this.context.router.push('/my-route')
};
render() {
return (
<button onClick={this.navigateToPage}>Go!</button>
);
}
}
MyComponent.contextTypes = {
router: React.PropTypes.object.isRequired
}
history
@Bobby所说的单例。您可以使用,context.router
但实际上很难对这些组件进行单元测试,因为仅实例化该组件将不会在上下文中具有此功能。
React-Router 4.x回答:
最后,我希望有一个历史对象,甚至可以携带外部组件。我想做的是拥有一个按需导入的history.js文件,并对其进行操作。
您只需更改BrowserRouter
为Router,然后指定历史记录属性。除了拥有自己的历史对象可以随意操作之外,这对您没有任何改变。
您需要安装历史记录,即使用的库react-router
。
用法示例,ES6表示法:
history.js
import createBrowserHistory from 'history/createBrowserHistory'
export default createBrowserHistory()
BasicComponent.js
import React, { Component } from 'react';
import history from './history';
class BasicComponent extends Component {
goToIndex(e){
e.preventDefault();
history.push('/');
}
render(){
return <a href="#" onClick={this.goToIndex}>Previous</a>;
}
}
编辑2018年4月16日:
如果必须从实际从Route
组件渲染的组件中导航,则还可以从props访问历史记录,如下所示:
BasicComponent.js
import React, { Component } from 'react';
class BasicComponent extends Component {
navigate(e){
e.preventDefault();
this.props.history.push('/url');
}
render(){
return <a href="#" onClick={this.navigate}>Previous</a>;
}
}
Router
代替BrowserRouter
。为您BrowserRouter
创建和维护history
对象。仅当您[“需要与Redux之类的状态管理工具进行深度集成”时,您才应该默认创建自己的应用程序。] reacttraining.com/react-router/web/api/Router
this.props.history
,但是我还没有找到一种解决方案可以帮助我在不是组件或未构建为React组件的任何其他工具的类中执行此操作您可以传递道具。感谢您的反馈:)
为此,谁不控制服务器端,因此使用哈希路由器v2:
将您的历史记录放入单独的文件中(例如,app_history.js ES6):
import { useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });
export default appHistory;
并在任何地方使用它!
您的react-router(app.js ES6)入口点:
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Redirect } from 'react-router'
import appHistory from './app_history'
...
const render((
<Router history={appHistory}>
...
</Router>
), document.querySelector('[data-role="app"]'));
您在任何组件(ES6)中的导航:
import appHistory from '../app_history'
...
ajaxLogin('/login', (err, data) => {
if (err) {
console.error(err); // login failed
} else {
// logged in
appHistory.replace('/dashboard'); // or .push() if you don't need .replace()
}
})
history
现在使用这两种方法
反应路由器V4
tl:dr;
if (navigate) {
return <Redirect to="/" push={true} />
}
简单和声明性的答案是,您需要<Redirect to={URL} push={boolean} />
结合使用setState()
push:布尔值-设置为 true时,重定向会将新条目推入历史记录,而不是替换当前条目。
import { Redirect } from 'react-router'
class FooBar extends React.Component {
state = {
navigate: false
}
render() {
const { navigate } = this.state
// here is the important part
if (navigate) {
return <Redirect to="/" push={true} />
}
// ^^^^^^^^^^^^^^^^^^^^^^^
return (
<div>
<button onClick={() => this.setState({ navigate: true })}>
Home
</button>
</div>
)
}
}
PS。该示例使用ES7 +属性初始化程序来初始化状态。如果您有兴趣,也请在这里查看。
withRouter
在重新载入的路线上时,使用不起作用。在我们的情况下,我们必须有选择地要么做setState
(导致return <Redirect>
)(如果已经在路线上),要么history.push()
从其他地方做。
警告:此答案仅涵盖1.0之前的ReactRouter版本
之后,我将用1.0.0-rc1用例更新此答案!
您也可以不使用mixins。
let Authentication = React.createClass({
contextTypes: {
router: React.PropTypes.func
},
handleClick(e) {
e.preventDefault();
this.context.router.transitionTo('/');
},
render(){
return (<div onClick={this.handleClick}>Click me!</div>);
}
});
带有上下文的陷阱是,除非您contextTypes
在类上定义,否则无法访问。
至于什么是上下文,它是一个像道具一样的对象,它从父级传递到子级,但是隐式地传递下来,而不必每次都重新声明道具。参见https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html
在正常工作之前,我尝试了至少10种方法!
@Felipe Skinner的withRouter
回答对我来说有点不知所措,而且我不确定是否要创建新的“ ExportedWithRouter”类名称。
大约是当前的React-Router 3.0.0和ES6,这是最简单,最干净的方法:
使用ES6的React-Router 3.xx:
import { withRouter } from 'react-router';
class Example extends React.Component {
// use `this.props.router.push('/some/path')` here
};
// Export the decorated class
export default withRouter(Example);
或者,如果不是您的默认班级,则按以下方式导出:
withRouter(Example);
export { Example };
请注意,在3.xx中,<Link>
组件本身正在使用router.push
,因此您可以通过传递<Link to=
标签的任何内容,例如:
this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'
200 OK
而不是30x
代码。如何解决此问题?
要以编程方式进行导航,您需要在的props.history中添加新的历史记录,这样可以为您完成工作:component
//using ES6
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick(e) {
e.preventDefault()
/* Look at here, you can add it here */
this.props.history.push('/redirected');
}
render() {
return (
<div>
<button onClick={this.handleClick}>
Redirect!!!
</button>
</div>
)
}
}
export default App;
对于ES6 + React组件,以下解决方案适用于我。
我关注了Felippe skinner,但添加了端到端解决方案来帮助像我这样的初学者。
以下是我使用的版本:
“反应路由器”:“ ^ 2.7.0”
“反应”:“ ^ 15.3.1”
以下是我的react组件,在其中我使用了react-router进行程序化导航:
import React from 'react';
class loginComp extends React.Component {
constructor( context) {
super(context);
this.state = {
uname: '',
pwd: ''
};
}
redirectToMainPage(){
this.context.router.replace('/home');
}
render(){
return <div>
// skipping html code
<button onClick={this.redirectToMainPage.bind(this)}>Redirect</button>
</div>;
}
};
loginComp.contextTypes = {
router: React.PropTypes.object.isRequired
}
module.exports = loginComp;
以下是我的路由器的配置:
import { Router, Route, IndexRedirect, browserHistory } from 'react-router'
render(<Router history={browserHistory}>
<Route path='/' component={ParentComp}>
<IndexRedirect to = "/login"/>
<Route path='/login' component={LoginComp}/>
<Route path='/home' component={HomeComp}/>
<Route path='/repair' component={RepairJobComp} />
<Route path='/service' component={ServiceJobComp} />
</Route>
</Router>, document.getElementById('root'));
可能不是最好的方法,但是...使用react-router v4,以下Typescript可能会给您一些帮助。
在下面的渲染组件中,例如LoginPage
,router
对象是可访问的,只需调用router.transitionTo('/homepage')
即可导航。
导航代码来自。
"react-router": "^4.0.0-2",
"react": "^15.3.1",
import Router from 'react-router/BrowserRouter';
import { History } from 'react-history/BrowserHistory';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
interface MatchWithPropsInterface {
component: typeof React.Component,
router: Router,
history: History,
exactly?: any,
pattern: string
}
class MatchWithProps extends React.Component<MatchWithPropsInterface,any> {
render() {
return(
<Match {...this.props} render={(matchProps) => (
React.createElement(this.props.component, this.props)
)}
/>
)
}
}
ReactDOM.render(
<Router>
{({ router }) => (
<div>
<MatchWithProps exactly pattern="/" component={LoginPage} router={router} history={history} />
<MatchWithProps pattern="/login" component={LoginPage} router={router} history={history} />
<MatchWithProps pattern="/homepage" component={HomePage} router={router} history={history} />
<Miss component={NotFoundView} />
</div>
)}
</Router>,
document.getElementById('app')
);
在React-Router v4和 ES6中
您可以使用withRouter
和this.props.history.push
。
import {withRouter} from 'react-router-dom';
class Home extends Component {
componentDidMount() {
this.props.history.push('/redirect-to');
}
}
export default withRouter(Home);
要withRouter
与基于类的组件一起使用,请尝试以下类似方法。不要忘记将export语句更改为使用withRouter
:
import { withRouter } from 'react-router-dom'
class YourClass extends React.Component {
yourFunction = () => {
doSomeAsyncAction(() =>
this.props.history.push('/other_location')
)
}
render() {
return (
<div>
<Form onSubmit={ this.yourFunction } />
</div>
)
}
}
export default withRouter(YourClass);
基于
何塞·安东尼奥·波斯蒂戈(JoséAntonio Postigo)和本·惠勒(Ben Wheeler)
的先前回答,是否具有新颖性?用Typescript编写,
并使用装饰器
或静态属性/字段
import * as React from "react";
import Component = React.Component;
import { withRouter } from "react-router";
export interface INavigatorProps {
router?: ReactRouter.History.History;
}
/**
* Note: goes great with mobx
* @inject("something") @withRouter @observer
*/
@withRouter
export class Navigator extends Component<INavigatorProps, {}>{
navigate: (to: string) => void;
constructor(props: INavigatorProps) {
super(props);
let self = this;
this.navigate = (to) => self.props.router.push(to);
}
render() {
return (
<ul>
<li onClick={() => this.navigate("/home")}>
Home
</li>
<li onClick={() => this.navigate("/about")}>
About
</li>
</ul>
)
}
}
/**
* Non decorated
*/
export class Navigator2 extends Component<INavigatorProps, {}> {
static contextTypes = {
router: React.PropTypes.object.isRequired,
};
navigate: (to: string) => void;
constructor(props: INavigatorProps, context: any) {
super(props, context);
let s = this;
this.navigate = (to) =>
s.context.router.push(to);
}
render() {
return (
<ul>
<li onClick={() => this.navigate("/home")}>
Home
</li>
<li onClick={() => this.navigate("/about")}>
About
</li>
</ul>
)
}
}
无论今天安装了什么npm。“反应路由器”:“ ^ 3.0.0”和
“ @ types /反应路由器”:“ ^ 2.0.41”
随着即将推出的React-Router v4,现在有了一种新的方法。
import { MemoryRouter, BrowserRouter } from 'react-router';
const navigator = global && global.navigator && global.navigator.userAgent;
const hasWindow = typeof window !== 'undefined';
const isBrowser = typeof navigator !== 'undefined' && navigator.indexOf('Node.js') === -1;
const Router = isBrowser ? BrowserRouter : MemoryRouter;
<Router location="/page-to-go-to"/>
react-lego是一个示例应用程序,显示了如何使用/更新react-router,并包含导航该应用程序的示例功能测试。
在React Router v4中。我遵循两种方式以编程方式进行路由。
1. this.props.history.push("/something/something")
2. this.props.history.replace("/something/something")
第二
替换历史记录堆栈上的当前条目
要获取道具的历史记录,您可能需要使用
如果您使用哈希或浏览器历史记录,则可以
hashHistory.push('/login');
browserHistory.push('/login');
hashHistory.push
,赋予“无法读取”未定义的属性“ push”。您从哪里导入这些?
对于当前的React版本(15.3),this.props.history.push('/location');
它对我有用,但显示以下警告:
browser.js:49警告:[react-router]
props.history
和context.history
已弃用。请使用context.router
。
我使用context.router
以下方法解决了问题:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.backPressed = this.backPressed.bind(this);
}
backPressed() {
this.context.router.push('/back-location');
}
...
}
MyComponent.contextTypes = {
router: React.PropTypes.object.isRequired
};
export default MyComponent;
React-Router V4
如果您使用的是版本4,则可以使用我的库(Shameless插件),您只需在其中分发一个动作,一切就可以正常工作!
dispatch(navigateTo("/aboutUs"));
那些在react-router v4上实现此功能时遇到问题的人。
这是一个用于从redux动作浏览react应用程序的可行解决方案。
history.js
import createHistory from 'history/createBrowserHistory'
export default createHistory()
App.js / Route.jsx
import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
<Route path="/test" component={Test}/>
</Router>
another_file.js或redux文件
import history from './history'
history.push('/test') // this should change the url and re-render Test component
感谢此评论: ReactTraining问题评论
如果碰巧通过react-router-redux将RR4与redux配对,也可以使用from的路由动作创建者react-router-redux
。
import { push, replace, ... } from 'react-router-redux'
class WrappedComponent extends React.Component {
handleRedirect(url, replaceState = true) {
replaceState
? this.props.dispatch(replace(url))
: this.props.dispatch(push(url))
}
render() { ... }
}
export default connect(null)(WrappedComponent)
如果使用redux thunk / saga管理异步流,请在redux操作中导入上述操作创建者,并使用mapDispatchToProps挂钩以响应组件。
react-router-redux
已弃用/存档很长时间了
您还可以useHistory
在无状态组件中使用挂钩。文档中的示例。
import { useHistory } from "react-router"
function HomeButton() {
const history = useHistory()
return (
<button type="button" onClick={() => history.push("/home")}>
Go home
</button>
)
}
注意:添加了挂钩
react-router@5.1.0
并要求react@>=16.8
正确的答案是在撰写本文时
this.context.router.history.push('/');
但是您需要将PropTypes添加到您的组件中
Header.contextTypes = {
router: PropTypes.object.isRequired
}
export default Header;
别忘了导入PropTypes
import PropTypes from 'prop-types';
也许不是最好的解决方案,但可以完成工作:
import { Link } from 'react-router-dom';
// create functional component Post
export default Post = () => (
<div className="component post">
<button className="button delete-post" onClick={() => {
// ... delete post
// then redirect, without page reload, by triggering a hidden Link
document.querySelector('.trigger.go-home').click();
}}>Delete Post</button>
<Link to="/" className="trigger go-home hidden"></Link>
</div>
);
基本上,与一个动作(在这种情况下为后删除)相关的逻辑最终将调用重定向触发器。这是不理想的,因为您将在标记中添加DOM节点“触发”,以便您可以在需要时方便地调用它。另外,您将直接与DOM交互,而在React组件中可能不需要DOM。
不过,这种重定向并不是经常需要的。因此,组件标记中的一个或两个额外的隐藏链接不会对您造成太大的伤害,特别是如果给它们提供有意义的名称。
这对我有用,不需要特殊的进口:
<input
type="button"
name="back"
id="back"
class="btn btn-primary"
value="Back"
onClick={() => { this.props.history.goBack() }}
/>
history
添加props
。这来自一个HoC,您需要先导入才能使用(直接发送给Route
该中心的组件会由该HoC自动包装,但是您需要导入Route
...)
改用hookrouter,这是react-router的现代替代品
https://www.npmjs.com/package/hookrouter
import { useRoutes, usePath, A} from "hookrouter";
回答关于通过选择框链接的问题,您可以执行以下操作:
navigate('/about');
对于React Router v4 +
假设您不需要在初始渲染本身期间进行导航(可以使用 <Redirect>
component)中,这就是我们在应用程序中所做的。
定义一个返回null的空路由,这将使您能够访问历史对象。您需要在您的顶级位置执行此操作Router
定义。
现在你可以做一切可以做的事历史一样history.push()
,history.replace()
,history.go(-1)
等!
import React from 'react';
import { HashRouter, Route } from 'react-router-dom';
let routeHistory = null;
export function navigateTo(path) {
if(routeHistory !== null) {
routeHistory.push(path);
}
}
export default function App(props) {
return (
<HashRouter hashType="noslash">
<Route
render={({ history }) => {
routeHistory = history;
return null;
}}
/>
{/* Rest of the App */}
</HashRouter>
);
}
react-router-dom:5.1.2
这个站点有3个页面,所有页面都在浏览器中动态呈现。
尽管该页面永远不会刷新,但是请注意当您浏览站点时,React Router如何使URL保持最新。这样可以保留浏览器的历史记录,确保后退按钮和书签之类的内容正常运行
一个开关看起来通过其所有的子元素,并呈现第一个其路径当前URL匹配。随时使用,只要您有多条路线,但一次只想渲染一条即可
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
</Switch>
</div>
</Router>
);
}
// You can think of these components as "pages"
// in your app.
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
function About() {
return (
<div>
<h2>About</h2>
</div>
);
}
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
</div>
);
}```
因此,在我的答案中,有3种不同的方式可以以编程方式重定向到路线。已经介绍了一些解决方案,但以下解决方案仅针对功能组件带有附加演示应用程序的。
使用以下版本:
反应:16.13.1
react-dom:16.13.1
反应路由器:5.2.0
react-router-dom:5.2.0
打字稿:3.7.2
组态:
因此,首先解决方案是使用HashRouter
,配置如下:
<HashRouter>
// ... buttons for redirect
<Switch>
<Route exact path="/(|home)" children={Home} />
<Route exact path="/usehistory" children={UseHistoryResult} />
<Route exact path="/withrouter" children={WithRouterResult} />
<Route exact path="/redirectpush" children={RedirectPushResult} />
<Route children={Home} />
</Switch>
</HashRouter>
从文档有关<HashRouter>
:
一个
<Router>
使用该URL(即哈希部分window.location.hash
),以确保您的UI同步与URL。
解决方案:
<Redirect>
使用推useState
:在功能组件(RedirectPushAction
来自我的存储库的组件)中使用useState
,我们可以用来处理重定向。棘手的部分是,一旦发生重定向,我们需要将redirect
状态设置回false
。通过延迟使用setTimeOut
,0
我们一直等到React提交Redirect
到DOM之后再取回按钮以便下次使用。
请在下面找到我的示例:
const [redirect, setRedirect] = useState(false);
const handleRedirect = useCallback(() => {
let render = null;
if (redirect) {
render = <Redirect to="/redirectpush" push={true} />
// in order wait until commiting to the DOM
// and get back the button for clicking next time
setTimeout(() => setRedirect(false), 0);
}
return render;
}, [redirect]);
return <>
{handleRedirect()}
<button onClick={() => setRedirect(true)}>
Redirect push
</button>
</>
从<Redirect>
文档:
渲染
<Redirect>
会导航到新位置。新位置将覆盖历史记录堆栈中的当前位置,就像服务器端重定向(HTTP 3xx)一样。
useHistory
钩子:在我的解决方案中,有一个名为的组件UseHistoryAction
,它表示以下内容:
let history = useHistory();
return <button onClick={() => { history.push('/usehistory') }}>
useHistory redirect
</button>
该
useHistory
挂钩使我们可以访问历史记录对象,这有助于我们以编程方式导航或更改路线。
withRouter
,得到了history
来自props
:创建了一个名为的组件WithRouterAction
,显示如下:
const WithRouterAction = (props:any) => {
const { history } = props;
return <button onClick={() => { history.push('/withrouter') }}>
withRouter redirect
</button>
}
export default withRouter(WithRouterAction);
从withRouter
文档中读取:
您可以通过高阶组件访问
history
对象的属性和最接近<Route>
的匹配项withRouter
。withRouter
将通更新match
,location
和history
道具给被包装的成分时,它呈现。
演示:
为了更好地表示,我用这些示例构建了一个GitHub存储库,请在下面找到它:
https://github.com/norbitrial/react-router-programmatically-redirect-examples
我希望这有帮助!