Reactjs 使用react router V4以编程方式导航

Reactjs 使用react router V4以编程方式导航,reactjs,ecmascript-6,react-router-v4,Reactjs,Ecmascript 6,React Router V4,我刚刚将react路由器从v3更换为v4。 但是我不知道如何以编程方式在组件的成员函数中导航。 i、 e在handleClick()函数中,我想在处理一些数据后导航到/path/some/where。 我过去常常这样做: 从'react router'导入{browserHistory} browserHistory.push(“/path/some/where”) 但是我在v4中找不到这样的接口。 如何使用v4导航?如果您针对的是浏览器环境,则需要使用react router dom包,而不

我刚刚将
react路由器
从v3更换为v4。
但是我不知道如何以编程方式在
组件的成员函数中导航。
i、 e在
handleClick()
函数中,我想在处理一些数据后导航到
/path/some/where
。 我过去常常这样做:

从'react router'导入{browserHistory}
browserHistory.push(“/path/some/where”)
但是我在v4中找不到这样的接口。

如何使用v4导航?

如果您针对的是浏览器环境,则需要使用
react router dom
包,而不是
react router
。他们采用了与React相同的方法,以分离核心(
React
)和平台特定的代码(
React dom
React native
),细微的区别是不需要安装两个单独的包,因此环境包包含您需要的所有内容。您可以将其添加到项目中,如下所示:

纱线添加反应器dom

npm i react路由器dom

您需要做的第一件事是提供一个
作为应用程序中最顶层的父组件
使用HTML5
历史
API并为您管理它,因此您不必担心自己实例化它并将其作为道具传递给
组件(在以前的版本中需要这样做)

在V4中,为了进行编程导航,您需要访问
历史记录
对象,该对象可通过React
上下文
访问,只要您的应用程序中有一个
提供程序组件作为最顶层的父级。库通过上下文公开
路由器
对象,该对象本身包含
历史
属性。
历史记录
界面提供了多种导航方法,例如
推送
替换
返回
。您可以检查整个属性和方法列表

Redux/Mobx用户的重要注意事项 如果您在应用程序中使用redux或mobx作为状态管理库,您可能会遇到组件问题,这些组件应该是位置感知的,但在触发URL更新后不会重新呈现。

这是因为
react router
使用上下文模型将
location
传递给组件

connect和observer都创建了组件,其shouldComponentUpdate方法对当前的道具和下一个道具进行了粗略的比较。只有在至少一个道具发生更改时,这些组件才会重新渲染。这意味着,为了确保它们在位置改变时更新,需要为它们提供一个在位置改变时改变的道具

解决这一问题的两种方法是:

  • 将连接的组件包装在无路径的
    中。当前的
    位置
    对象是
    传递给它呈现的组件的道具之一
  • withRouter
    高阶组件包装您连接的组件,这实际上具有相同的效果,并作为道具注入
    location
撇开这一点不谈,按推荐顺序,有四种编程导航方式:

1.-使用
组件
可以提升声明式风格。在v4之前,
组件被放置在组件层次结构的顶部,必须事先考虑路由结构。但是,现在您可以在树中的任何位置使用
组件,从而可以根据URL使用更好的控件进行有条件渲染<代码>路由
匹配
位置
历史
作为道具注入组件。导航方法(如
push
replace
goBack
…)作为
历史对象的属性提供

使用
路径
渲染某物有三种方法,即使用
组件
渲染
子级
道具,但在同一
路径
中不要使用多个。选择取决于用例,但基本上前两个选项仅在
路径
与url位置匹配时才会呈现组件,而对于
子项
,无论路径是否与位置匹配,都会呈现组件(用于根据url匹配调整UI)

如果要自定义组件渲染输出,则需要将组件封装在函数中,并使用
渲染
选项,以便向组件传递除
匹配
位置
历史
之外所需的任何其他道具。举例说明:

import { BrowserRouter as Router } from 'react-router-dom'

const ButtonToNavigate = ({ title, history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    {title}
  </button>
);

const SomeComponent = () => (
  <Route path="/" render={(props) => <ButtonToNavigate {...props} title="Navigate elsewhere" />} />
)    

const App = () => (
  <Router>
    <SomeComponent /> // Notice how in v4 we can have any other component interleaved
    <AnotherComponent />
  </Router>
);
3.-使用
重定向
组件呈现
将导航到新位置。但是请记住,默认情况下,当前位置会被新位置替换,就像服务器端重定向(HTTP 3xx)一样。新位置由
to
prop提供,可以是字符串(要重定向到的URL)或
location
对象。如果您想将一个新条目推送到历史记录中,请同时传递一个
push
prop并将其设置为
true

<Redirect to="/your-new-location" push />
不用说,还有其他路由器组件是为非浏览器生态系统设计的,例如
,它复制内存中的导航堆栈,并以React-Native平台为目标,可通过
React-Router-Native
包获得

对于任何进一步的参考,请毫不犹豫地查看。还有一个由该库的一位合著者编写的示例,它对react路由器v4 highlig进行了非常酷的介绍
<Redirect to="/your-new-location" push />
const ButtonToNavigate = (props, context) => (
  <button
    type="button"
    onClick={() => context.router.history.push('/my-new-location')}
  >
    Navigate to a new location
  </button>
);

ButtonToNavigate.contextTypes = {
  router: React.PropTypes.shape({
    history: React.PropTypes.object.isRequired,
  }),
};
// src/history.js

import createHistory from 'history/createBrowserHistory';
export default createHistory();`
// src/App.js

import history from '../your/path/to/history.js;'
<Router history={history}>
// Route tags here
</Router>
import history from '../your/path/to/history.js;'
history.push('new/path/here/');
this.state = {
    redirectTo: null
} 
this.clickhandler = this.clickhandler.bind(this);
render(){
    return (
        <div>
        { this.state.redirectTo ?
            <Redirect to={{ pathname: this.state.redirectTo }} /> : 
            (
             <div>
               ..
             <button onClick={ this.clickhandler } />
              ..
             </div>
             )
         }
 this.setState({ redirectTo: '/path/some/where' });
if (navigate) {
  return <Redirect to="/" 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>
    )
  }
}
import { Component } from 'react'
import { BrowserRouter as Router, Link } from 'react-router-dom'

class App extends Component {
  constructor(props) {
    super(props)

    /** @type BrowserRouter */
    this.router = undefined
  }

  async handleSignFormSubmit() {
    await magic()
    this.router.history.push('/')
  }

  render() {
    return (
      <Router ref={ el => this.router = el }>
        <Link to="/signin">Sign in</Link>
        <Route path="/signin" exact={true} render={() => (
          <SignPage onFormSubmit={ this.handleSignFormSubmit } />
        )} />
      </Router>
    )
  }
}
// history.js
if(__SERVER__) {
    module.exports = {};
} else {
    module.exports = require('history').createBrowserHistory();
}
plugins: [
    new DefinePlugin({
        '__SERVER__': 'false',
        '__BROWSER__': 'true', // you really only need one of these, but I like to have both
    }),
import history from './history';
// LinkButton.js

import React from "react";
import PropTypes from "prop-types";
import {Route} from 'react-router-dom';

export default class LinkButton extends React.Component {

    render() {
        return (
            <Route render={({history}) => (
                <button {...this.props}
                       onClick={() => {
                           history.push(this.props.to)
                       }}>
                    {this.props.children}
                </button>
            )}/>
        );
    }
}

LinkButton.propTypes = {
    to: PropTypes.string.isRequired
};
<LinkButton className="btn btn-primary" to="/location">
    Button Text
</LinkButton>
import React from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';

const NavButton = (props) => (
  <Button onClick={() => props.history.push(props.to)}>
    {props.children}
  </Button>
);

NavButton.propTypes = {
  history: PropTypes.shape({
    push: PropTypes.func.isRequired
  }),
  to: PropTypes.string.isRequired
};

export default withRouter(NavButton);
<NavButton to="/somewhere">Click me</NavButton>
import {Route} from 'react-router-dom';
<Route
  exact
  path='/posts/add'
  render={({history}) => (
    <PostAdd history={history} />
  )}
/>
this.props.history.push('/');
import { withRouter } from 'react-router-dom';

const SomeComponent = withRouter(({ history }) => (
    <div onClick={() => history.push('/path/some/where')}>
        some clickable element
    </div>); 
);

export default SomeComponent;
// history is already a dependency or React Router, but if don't have it then try npm install save-dev history

import createHistory from "history/createBrowserHistory"

// in your function then call add the below 
const history = createHistory();
// Use push, replace, and go to navigate around.
history.push("/home");
function getSubdomain(hostname) {
    let regexParse = new RegExp('[a-z\-0-9]{2,63}\.[a-z\.]{2,5}$');
    let urlParts = regexParse.exec(hostname);
    return hostname.replace(urlParts[0], '').slice(0, -1);
}

class App extends Component {

    constructor(props) {
        super(props);


        this.state = {
            hostState: true
        };

        if (getSubdomain(window.location.hostname).length > 0) {
            this.state.hostState = false;
            window.history.pushState('', '', './login');
        } else {
            console.log(getSubdomain(window.location.hostname));
        }

    }


    render() {
        return (

            <BrowserRouter>
                {this.state.hostState ? (
                    <div>
                        <Route path="/login" component={LoginContainer}/>
                        <Route path="/" component={PublicContainer}/>
                    </div>
                ) : (
                    <div>
                        <Route path="/login" component={LoginContainer}/>
                    </div>
                )

                }
            </BrowserRouter>)
    }


}
window.history.pushState('', '', './login');
import { useHistory } from "react-router-dom";

const MyComponent = () => {
  const history = useHistory();
  
  return (
    <button onClick={() => history.push("/about")}>
      Click me
    </button>
  );
}
class HomePage extends React.Component {
  render() {
    const { history } = this.props;

    return (
      <div>
        <button onClick={() => history.push("/projects")}>
          Projects
        </button>
      </div>
    );
  }
}
import { withRouter } from "react-router";

const LogoutButton = withRouter(({ history }) => {
  return (
    <button onClick={() => history.push("/login")}>
      Logout
    </button>
  );
});

export default LogoutButton;
this.props.history.push("/url")
import {withRouter} from 'react-router-dom'
export default withRouter(MyComponent)  
import { useHistory } from "react-router-dom";

function HomeButton() {
  const history = useHistory();

  function handleClick() {
    history.push("/path/some/where");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}