React-router:如何手动调用 Link? [英] React-router: How to manually invoke Link?
问题描述
我是 ReactJS 和 React-Router 的新手.我有一个组件,它通过 props 接收来自 react-router 的 对象.每当用户单击此组件内的下一步"按钮时,我都想手动调用
对象.
现在,我正在使用 refs 访问 支持实例 并手动点击 生成.
问题:有没有办法手动调用链接(例如this.props.next.go
)?
这是我当前的代码:
//在 MasterPage.js 中var sampleLink = <Link to="/sample">Go To Sample</Link><Document next={sampleLink}/>//在Document.js中...var Document = React.createClass({_onClickNext:函数(){var next = this.refs.next.getDOMNode();next.querySelectorAll('a').item(0).click();//这对我来说听起来像是hack},渲染:函数(){返回 (...<div ref="next">{this.props.next} <img src="rightArrow.png" onClick={this._onClickNext}/></div>...);}});...
这是我想要的代码:
//在 MasterPage.js 中var sampleLink = <Link to="/sample">Go To Sample</Link><Document next={sampleLink}/>//在Document.js中...var Document = React.createClass({渲染:函数(){返回 (...<div onClick={this.props.next.go}>{this.props.next.label} <img src="rightArrow.png"/>
...);}});...
React Router v5 - React 16.8+ with Hooks (updated 09/23/2020)
如果您正在利用 React Hooks,您可以利用 useHistory
来自 React Router v5 的 API.
import React, {useCallback} from 'react';从'react-router-dom'导入{useHistory};导出默认函数 StackOverflowExample() {const 历史 = useHistory();const handleOnClick = useCallback(() => history.push('/sample'), [history]);返回 (<按钮类型=按钮"onClick={handleOnClick}>回家按钮>);}
如果您不想使用useCallback
const handleOnClick = () =>history.push('/sample');
React Router v4 - 重定向组件
v4 推荐的方法是允许您的渲染方法捕获重定向.使用 state 或 props 来确定是否需要显示重定向组件(然后触发重定向).
import { Redirect } from 'react-router';//... 你的类实现handleOnClick = () =>{//一些动作...//然后重定向this.setState({redirect: true});}使成为() {如果(this.state.redirect){return <Redirect push to="/sample";/>;}return <button onClick={this.handleOnClick} type=button">Button</button>;}
参考:https://reacttraining.com/react-router/web/api/重定向
React Router v4 - 参考路由器上下文
您还可以利用暴露给 React 组件的 Router
上下文.
static contextTypes = {路由器:PropTypes.shape({历史:PropTypes.shape({推送:PropTypes.func.isRequired,替换:PropTypes.func.isRequired}).是必须的,静态上下文:PropTypes.object}).是必须的};handleOnClick = () =>{this.context.router.push('/sample');}
这就是
在幕后的工作原理.
React Router v4 - 外部改变历史对象
如果你仍然需要做一些类似于 v2 的实现,你可以创建一个 BrowserRouter
的副本,然后将 history
作为一个可导出的常量公开.下面是一个基本示例,但如果需要,您可以编写它以将其注入可自定义的道具.有关于生命周期的注意事项,但它应该总是重新渲染路由器,就像在 v2 中一样.这对于在来自操作函数的 API 请求之后重定向非常有用.
//浏览器路由器文件...从'history/createBrowserHistory'导入createHistory;从反应路由器"导入{路由器};导出 const 历史记录 = createHistory();导出默认类 BrowserRouter 扩展组件 {使成为() {return <Router history={history} children={this.props.children}/>}}//你的主文件...从 './relative/path/to/BrowserRouter' 导入 BrowserRouter;从'react-dom'导入{渲染};使成为(<浏览器路由器><应用程序/></BrowserRouter>);//一些文件...你没有 React 实例引用的地方从'./relative/path/to/BrowserRouter'导入{历史};history.push('/sample');
最新 BrowserRouter
扩展:https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js
React 路由器 v2
向 browserHistory
实例推送一个新状态:
import {browserHistory} from 'react-router';//...browserHistory.push('/sample');
参考:https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md
I'm new to ReactJS and to React-Router. I have a component that receives through props a <Link/>
object from react-router. Whenever the user clicks on a 'next' button inside this component I want to invoke <Link/>
object manually.
Right now, I'm using refs to access the backing instance and manually clicking on the 'a' tag that <Link/>
generates.
Question: Is there a way to manually invoke the Link (e.g. this.props.next.go
)?
This is the current code I have:
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />
//in Document.js
...
var Document = React.createClass({
_onClickNext: function() {
var next = this.refs.next.getDOMNode();
next.querySelectorAll('a').item(0).click(); //this sounds like hack to me
},
render: function() {
return (
...
<div ref="next">{this.props.next} <img src="rightArrow.png" onClick={this._onClickNext}/></div>
...
);
}
});
...
This is the code I would like to have:
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />
//in Document.js
...
var Document = React.createClass({
render: function() {
return (
...
<div onClick={this.props.next.go}>{this.props.next.label} <img src="rightArrow.png" /> </div>
...
);
}
});
...
React Router v5 - React 16.8+ with Hooks (updated 09/23/2020)
If you're leveraging React Hooks, you can take advantage of the useHistory
API that comes from React Router v5.
import React, {useCallback} from 'react';
import {useHistory} from 'react-router-dom';
export default function StackOverflowExample() {
const history = useHistory();
const handleOnClick = useCallback(() => history.push('/sample'), [history]);
return (
<button type="button" onClick={handleOnClick}>
Go home
</button>
);
}
Another way to write the click handler if you don't want to use useCallback
const handleOnClick = () => history.push('/sample');
React Router v4 - Redirect Component
The v4 recommended way is to allow your render method to catch a redirect. Use state or props to determine if the redirect component needs to be shown (which then trigger's a redirect).
import { Redirect } from 'react-router';
// ... your class implementation
handleOnClick = () => {
// some action...
// then redirect
this.setState({redirect: true});
}
render() {
if (this.state.redirect) {
return <Redirect push to="/sample" />;
}
return <button onClick={this.handleOnClick} type="button">Button</button>;
}
Reference: https://reacttraining.com/react-router/web/api/Redirect
React Router v4 - Reference Router Context
You can also take advantage of Router
's context that's exposed to the React component.
static contextTypes = {
router: PropTypes.shape({
history: PropTypes.shape({
push: PropTypes.func.isRequired,
replace: PropTypes.func.isRequired
}).isRequired,
staticContext: PropTypes.object
}).isRequired
};
handleOnClick = () => {
this.context.router.push('/sample');
}
This is how <Redirect />
works under the hood.
React Router v4 - Externally Mutate History Object
If you still need to do something similar to v2's implementation, you can create a copy of BrowserRouter
then expose the history
as an exportable constant. Below is a basic example but you can compose it to inject it with customizable props if needed. There are noted caveats with lifecycles, but it should always rerender the Router, just like in v2. This can be useful for redirects after an API request from an action function.
// browser router file...
import createHistory from 'history/createBrowserHistory';
import { Router } from 'react-router';
export const history = createHistory();
export default class BrowserRouter extends Component {
render() {
return <Router history={history} children={this.props.children} />
}
}
// your main file...
import BrowserRouter from './relative/path/to/BrowserRouter';
import { render } from 'react-dom';
render(
<BrowserRouter>
<App/>
</BrowserRouter>
);
// some file... where you don't have React instance references
import { history } from './relative/path/to/BrowserRouter';
history.push('/sample');
Latest BrowserRouter
to extend: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js
React Router v2
Push a new state to the browserHistory
instance:
import {browserHistory} from 'react-router';
// ...
browserHistory.push('/sample');
Reference: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md
这篇关于React-router:如何手动调用 Link?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!