通过react-router
我可以使用Link
元素来创建由react路由器本地处理的链接。
我在内部看到它调用this.context.transitionTo(...)
。
我想从下拉列表中进行导航,而不是从链接进行导航。 如何在代码中执行此操作? 这是什么this.context
?
我看到了Navigation
混合器,但是没有混合器可以做到吗?
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不存在。 您应该使用
在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答案
我不会介绍升级细节。 您可以在《 升级指南》中阅读有关内容
关于此问题的主要更改是从Navigation mixin到History的更改。 现在,它使用浏览器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 (Click me!);
}
});
我无需调用.context
就可以调用transitionTo()
或者您可以尝试精美的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 (Click me!);
}
}
Authentication.contextTypes = {
router: React.PropTypes.func.isRequired
};
React-Router-Redux
注意:如果您使用Redux,还有另一个名为React-Router-Redux的项目,它使用与React-Redux相同的方法为您提供ReactRouter的redux绑定。
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
警告:此答案仅涵盖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 (Click me!);
}
});
带有上下文的陷阱是,除非您在类上定义contextTypes
,否则无法访问它。
至于什么是上下文,它是一个像道具一样的对象,它从父级传递到子级,但是隐式地传递下来,而不必每次都重新声明道具。 参见https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html
React-路由器v2
对于最新版本( v2.0.0-rc5
),推荐的导航方法是直接推送到历史单例。 您可以在Components doc之外的导航中看到这一点。
相关摘录:
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
如果使用较新的react-router API,则需要在组件内部使用this.props
的history
,因此:
this.props.history.push('/some/path');
它还提供pushState
但已记录的警告已弃用。
如果使用react-router-redux
,它提供了一个push
函数,您可以像这样调度:
import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));
但是,这只能用于更改URL,而不能实际导航到页面。
这是在ES6上使用react-router v2.0.0
v2.0.0的方法 。 react-router
已从mixins移开。
import React from 'react';
export default class MyComponent extends React.Component {
navigateToPage = () => {
this.context.router.push('/my-route')
};
render() {
return (
);
}
}
MyComponent.contextTypes = {
router: React.PropTypes.object.isRequired
}
对于这一点,谁不控制服务器端,因此使用哈希路由器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((
...
), 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()
}
})
对于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
// skipping html code
;
}
};
loginComp.contextTypes = {
router: React.PropTypes.object.isRequired
}
module.exports = loginComp;
以下是我的路由器的配置:
import { Router, Route, IndexRedirect, browserHistory } from 'react-router'
render(
, document.getElementById('root'));
随着即将推出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;
react-lego是一个示例应用程序,显示了如何使用/更新react-router ,并且包括导航该应用程序的示例功能测试。
可能不是最好的方法,但是...使用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 { render() { return( ( React.createElement(this.props.component, this.props) )} /> ) } } ReactDOM.render( {({ router }) => ( )} , document.getElementById('app') );
在当前的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"));
特里普勒
在正常工作之前,我尝试了至少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中, 组件本身正在使用
router.push
,因此您可以将传递标记的任何内容传递给它,例如:
this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'
根据先前的答案
来自JoséAntonio Postigo和Ben Wheeler
新奇? 用打字稿写
和装饰器的使用
或静态属性/字段
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{
navigate: (to: string) => void;
constructor(props: INavigatorProps) {
super(props);
let self = this;
this.navigate = (to) => self.props.router.push(to);
}
render() {
return (
- this.navigate("/home")}>
Home
- this.navigate("/about")}>
About
)
}
}
/**
* Non decorated
*/
export class Navigator2 extends Component {
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 (
- this.navigate("/home")}>
Home
- this.navigate("/about")}>
About
)
}
}
无论今天安装了什么npm。 “ react-router”:“ ^ 3.0.0”和
“ @ types / react-router”:“ ^ 2.0.41”
带有钩子的React Router v5.1.0
如果您使用React> 16.8.0和功能组件,则在React Router> 5.1.0中有一个新的useHistory
挂钩。
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
);
}
反应路由器v4
使用React Router v4,您可以采用三种方法在组件内进行编程路由。
withRouter
高阶组件。
context
。 React Router主要是history
库的包装器。 history
处理与浏览器window.history
。交互的history
,以及浏览器和哈希历史记录。 它还提供了内存历史记录,这对于没有全局历史记录的环境很有用。 这在使用Node进行移动应用程序开发( react-native
)和单元测试中特别有用。
history
实例有两种导航方法: push
和replace
。 如果您将history
视为访问过的位置数组,则push
将向该位置添加新位置,而replace
将用新位置replace
该数组中的当前位置。 通常,您在导航时会希望使用push
方法。
在早期版本的React Router中,您必须创建自己的history
实例,但是在v4中,
,
和
组件将为您创建浏览器,哈希和内存实例。 React Router通过router
对象下的上下文使与路由器关联的history
实例的属性和方法可用。
withRouter
高阶组件 withRouter
高阶组件将注入history
对象作为该组件的支持。 这使您无需处理context
即可访问push
和replace
方法。
import { withRouter } from 'react-router-dom'
// this also works with react-router-native
const Button = withRouter(({ history }) => (
))
组件不仅用于匹配位置。 您可以渲染无路径的路线, 它将始终与当前位置匹配 。
组件传递与withRouter
相同的道具,因此您将能够通过history
道具访问history
方法。
import { Route } from 'react-router-dom'
const Button = () => (
(
)} />
)
但是你可能不应该
最后一个选项是只有在您熟悉使用React的上下文模型时才应使用的选项。 尽管上下文是一个选项,但应该强调的是上下文是不稳定的API,React在其文档中有“ 为什么不使用上下文”一节。 因此,使用后果自负!
const Button = (props, context) => (
)
// 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是最简单的实现方式,因此对于大多数用例来说,它们是最好的选择。
此外,您可以从以下链接中获得有关路由,URL参数和嵌套路由的更多知识。
在React JS中路由
-逐步说明如何在ReactJS中集成react-router
使用React Router的URL参数
-在这里您可以了解如何使用React Router设置URL参数。 URL参数路由的主要用途是根据其动态URL呈现相同的组件。
React JS中的嵌套路由
-如果要在主路径中加载子路径,则必须创建嵌套路径。 这是它的现场示例。
希望能帮到你!
要以编程方式进行导航,您需要将新的历史记录推送到 component
的props.history ,这样可以为您完成工作:
//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 (
)
}
}
export default App;
React-Router 4.x回答:
最后,我希望有一个历史对象,甚至可以携带外部组件。 我想做的是拥有一个按需导入的history.js文件,并对其进行操作。
您只需要将BrowserRouter
更改为Router,然后指定历史记录BrowserRouter
即可。 除了拥有自己的历史对象可以随意操作之外,这对您没有任何改变。
您需要安装历史记录 , 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 Previous;
}
}
编辑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 Previous;
}
}
如果您使用哈希或浏览器历史记录,则可以
hashHistory.push('/login');
browserHistory.push('/login');
在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);
只需使用this.props.history.push('/where/to/go');
反应路由器V4
tl:dr;
if (navigate) {
return
}
简单且声明性的答案是,您需要将
与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
}
// ^^^^^^^^^^^^^^^^^^^^^^^
return (
)
}
}
完整的例子在这里 。 在这里阅读更多。
PS。 该示例使用ES7 +属性初始化程序来初始化状态。 如果您有兴趣,也请在这里查看。
也许不是最好的解决方案,但可以完成工作:
import { Link } from 'react-router-dom';
// create functional component Post
export default Post = () => (
);
基本上,与一个动作(在这种情况下为后删除)相关的逻辑最终将调用重定向触发器。 这不是理想的,因为您将在标记中添加DOM节点“触发”,以便您在需要时可以方便地调用它。 另外,您将直接与DOM交互,而在React组件中可能不需要DOM。
不过,这种重定向并不是经常需要的。 因此,组件标记中的一个或两个额外的隐藏链接不会对您造成太大的伤害,特别是如果给它们提供有意义的名称。
正确的答案是在撰写本文时适合我的
this.context.router.history.push('/');
但是您需要将PropTypes添加到您的组件中
Header.contextTypes = {
router: PropTypes.object.isRequired
}
export default Header;
不要忘记导入PropTypes
import PropTypes from 'prop-types';
如果发生配对RR4 W /通过Redux的反应,路由器终极版 ,使用路由动作的创造者,从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挂钩以响应组件,可能会更好。
要将withRouter
与基于类的组件一起使用,请尝试以下类似方法。 别忘了更改export语句以与withRouter
一起使用:
import { withRouter } from 'react-router-dom'
class YourClass extends React.Component {
yourFunction = () => {
doSomeAsyncAction(() =>
this.props.history.push('/other_location')
)
}
render() {
return (
)
}
}
export default withRouter(YourClass);
在React Router v4中。 我遵循两种方式以编程方式进行路由。
1. this.props.history.push("/something/something")
2. this.props.history.replace("/something/something")
第二
替换历史记录堆栈上的当前条目
要获取道具的历史记录,您可能需要使用
与路由器
那些在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'
...
another_file.js或redux文件
import history from './history'
history.push('/test') // this should change the url and re-render Test component
感谢此评论: ReactTraining问题评论
简单的反应路由:
链接到我的代码沙箱。 它还有其他一些简单的react-redux程序。
对于React Router v4 +
假设您不需要在初始渲染过程中进行导航(可以使用
组件),这就是我们在应用程序中所做的。
定义一个返回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 (
{
routeHistory = history;
return null;
}}
/>
{/* Rest of the App */}
);
}
这对我有用,不需要特殊的进口:
{ this.props.history.goBack() }}
/>
您还可以在无状态组件中使用useHistory
挂钩。 文档中的示例。
import { useHistory } from "react-router"
function HomeButton() {
const history = useHistory()
return (
)
}
注意:钩子已添加到
[email protected]
并且需要react@>=16.8
因此,在我的回答中,有3种不同的方式可以以编程方式重定向到路线。 已经介绍了一些解决方案,但以下解决方案仅针对带有附加演示应用程序的功能组件 。
使用以下版本:
反应: 16.12.0
react-dom: 16.12.0
反应路由器: 5.1.2
react-router-dom: 5.1.2
打字稿: 3.7.2
组态:
因此,首先解决方案是使用HashRouter
,其配置如下:
// ... buttons for redirect
从有关
的文档中 :
使用URL的哈希部分(即
window.location.hash
)使您的UI与URL保持同步。
解决方案:
推送使用useState
: 在功能组件(我的存储库中的RedirectPushAction
组件)中使用,我们可以使用useState
来处理重定向。 棘手的部分是,一旦发生重定向,我们需要将redirect
状态设置回false
。 通过将setTimeOut
为0
延迟,我们等待,直到React将Redirect
提交到DOM,然后取回该按钮以便下次使用。
请在下面找到我的示例:
const [redirect, setRedirect] = useState(false);
const handleRedirect = useCallback(() => {
let render = null;
if (redirect) {
render =
// 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()}
>
从
文档中:
渲染
将导航到新位置。 新位置将覆盖历史记录堆栈中的当前位置,就像服务器端重定向(HTTP 3xx)一样。
useHistory
钩子: 在我的解决方案中,有一个名为UseHistoryAction
的组件,它表示以下内容:
let history = useHistory();
return
useHistory
挂钩使我们可以访问历史记录对象,这有助于我们以编程方式导航或更改路线。
withRouter
,从props
获取history
: 创建了一个名为WithRouterAction
组件,显示如下:
const WithRouterAction = (props:any) => {
const { history } = props;
return
}
export default withRouter(WithRouterAction);
从withRouter
文档中阅读:
您可以通过
withRouter
高阶组件访问history
对象的属性和最接近的匹配项。 每当呈现时,
withRouter
都会将更新的match
,location
和history
道具传递给包装的组件。
演示:
为了更好地表示,我用这些示例构建了一个GitHub存储库,请在下面找到它:
https://github.com/norbitrial/react-router-programmatically-redirect-examples
我希望这有帮助!