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

查看:111
本文介绍了React-router:如何手动调用链接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是ReactJS和React-Router的新手.我有一个通过props从 react-router 接收<Link/>对象的组件.每当用户单击该组件内的下一个"按钮时,我都想手动调用<Link/>对象.

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.

现在,我正在使用 refs 访问后备实例,并手动单击<Link/>生成的'a'标记.

Right now, I'm using refs to access the backing instance and manually clicking on the 'a' tag that <Link/> generates.

问题:是否可以手动调用链接(例如this.props.next.go)?

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>
         ...
      );
   }
});
...

这是我想要的代码:

//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+(更新于09/23/2020)

如果您利用反应钩子,则可以利用来自React Router v5的API.

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>
  );
}

如果不想使用useCallback

const handleOnClick = () => history.push('/sample');

反应路由器v4-重定向组件

v4推荐的方法是允许您的render方法捕获重定向.使用状态或道具来确定是否需要显示重定向组件(然后触发重定向).

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>;
}

参考: https://reacttraining.com/react-router/web/api/重定向

您还可以利用暴露给React组件的Router上下文.

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');
}

这是<Redirect />在后台运行的方式.

This is how <Redirect /> works under the hood.

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

如果仍然需要执行类似于v2的实现,则可以创建BrowserRouter的副本,然后将history公开为可导出常量.以下是一个基本示例,但是您可以根据需要将其组合为可自定义的道具.有一些关于生命周期的警告,但就像在v2中一样,它应始终重新渲染路由器.这对于从操作功能发出API请求后的重定向很有用.

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');

最新的BrowserRouter扩展:将新状态推入browserHistory实例:

import {browserHistory} from 'react-router';
// ...
browserHistory.push('/sample');

参考: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md

这篇关于React-router:如何手动调用链接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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