React-router:如何手动调用 Link? [英] React-router: How to manually invoke Link?

查看:56
本文介绍了React-router:如何手动调用 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');}

这就是 在幕后的工作原理.

参考:https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Redirect.js#L46,L60

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.

Reference: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Redirect.js#L46,L60

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆