Programmatically navigate using react router

后端 未结 30 2367
無奈伤痛
無奈伤痛 2020-11-21 05:18

With react-router I can use the Link element to create links which are natively handled by react router.

I see internally it calls t

相关标签:
30条回答
  • 2020-11-21 05:31

    React-Router V4

    if you're using version 4 then you can use my library (Shameless plug) where you simply dispatch an action and everything just works!

    dispatch(navigateTo("/aboutUs"));
    

    trippler

    0 讨论(0)
  • 2020-11-21 05:34

    If happen to pair RR4 w/ redux through react-router-redux, use the routing action creators from react-router-redux is a option as well.

    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)
    

    If use redux thunk/saga to manage async flow, import the above action creators in redux actions and hook to react components using mapDispatchToProps might be better.

    0 讨论(0)
  • 2020-11-21 05:35

    To do the navigation programmatically, you need to push a new history to the props.history in your component, so something like this can do the work for you:

    //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 (
          <div>
            <button onClick={this.handleClick}>
              Redirect!!!
            </button>
          </div>
        )
      }
    }
    
    export default App;
    
    0 讨论(0)
  • 2020-11-21 05:36

    React Router v5.1.0 with hooks

    There is a new useHistory hook in React Router >5.1.0 if you are using React >16.8.0 and functional components.

    import { useHistory } from "react-router-dom";
    
    function HomeButton() {
      const history = useHistory();
    
      function handleClick() {
        history.push("/home");
      }
    
      return (
        <button type="button" onClick={handleClick}>
          Go home
        </button>
      );
    }
    

    React Router v4

    With v4 of React Router, there are three approaches that you can take to programmatic routing within components.

    1. Use the withRouter higher-order component.
    2. Use composition and render a <Route>
    3. Use the context.

    React Router is mostly a wrapper around the history library. history handles interaction with the browser's window.history for you with its browser and hash histories. It also provides a memory history which is useful for environments that don't have a global history. This is particularly useful in mobile app development (react-native) and unit testing with Node.

    A history instance has two methods for navigating: push and replace. If you think of the history as an array of visited locations, push will add a new location to the array and replace will replace the current location in the array with the new one. Typically you will want to use the push method when you are navigating.

    In earlier versions of React Router, you had to create your own history instance, but in v4 the <BrowserRouter>, <HashRouter>, and <MemoryRouter> components will create a browser, hash, and memory instances for you. React Router makes the properties and methods of the history instance associated with your router available through the context, under the router object.

    1. Use the withRouter higher-order component

    The withRouter higher-order component will inject the history object as a prop of the component. This allows you to access the push and replace methods without having to deal with the context.

    import { withRouter } from 'react-router-dom'
    // this also works with react-router-native
    
    const Button = withRouter(({ history }) => (
      <button
        type='button'
        onClick={() => { history.push('/new-location') }}
      >
        Click Me!
      </button>
    ))
    

    2. Use composition and render a <Route>

    The <Route> component isn't just for matching locations. You can render a pathless route and it will always match the current location. The <Route> component passes the same props as withRouter, so you will be able to access the history methods through the history prop.

    import { Route } from 'react-router-dom'
    
    const Button = () => (
      <Route render={({ history}) => (
        <button
          type='button'
          onClick={() => { history.push('/new-location') }}
        >
          Click Me!
        </button>
      )} />
    )
    

    3. Use the context*

    But you probably should not

    The last option is one that you should only use if you feel comfortable working with React's context model (React's Context API is stable as of v16).

    const Button = (props, context) => (
      <button
        type='button'
        onClick={() => {
          // context.history.push === history.push
          context.history.push('/new-location')
        }}
      >
        Click Me!
      </button>
    )
    
    // 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 and 2 are the simplest choices to implement, so for most use cases, they are your best bets.

    0 讨论(0)
  • 2020-11-21 05:36

    Try hookrouter instead, "the modern alternative to react-router"

    https://www.npmjs.com/package/hookrouter

    import { useRoutes, usePath, A} from "hookrouter";
    

    to answer OP question about linking through select box you can do it:

    navigate('/about');
    

    *** UPDATED ANSWER ***

    I think hook-router was a good starter kit and helped me learn about routing but have since updated to react-router for it's history and query parameter handling.

    import { useLocation, useHistory } from 'react-router-dom';
    
    
    const Component = (props) => {
        const history = useHistory();
        
        // Programmatically navigate
        history.push(newUrlString);
    }
    

    You push where you want to navigate into the location.history.

    0 讨论(0)
  • 2020-11-21 05:37

    React-Router 5.1.0+ Answer (using hooks and React >16.8)

    You can use the new useHistory hook on Functional Components and Programmatically navigate:

    import { useHistory } from "react-router-dom";
    
    function HomeButton() {
      let history = useHistory();
      // use history.push('/some/path') here
    };
    

    React-Router 4.0.0+ Answer

    In 4.0 and above, use the history as a prop of your component.

    class Example extends React.Component {
       // use `this.props.history.push('/some/path')` here
    };
    

    NOTE: this.props.history does not exist in the case your component was not rendered by <Route>. You should use <Route path="..." component={YourComponent}/> to have this.props.history in YourComponent

    React-Router 3.0.0+ Answer

    In 3.0 and above, use the router as a prop of your component.

    class Example extends React.Component {
       // use `this.props.router.push('/some/path')` here
    };
    

    React-Router 2.4.0+ Answer

    In 2.4 and above, use a higher order component to get the router as a prop of your component.

    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+ Answer

    This version is backwards compatible with 1.x so there's no need to an Upgrade Guide. Just going through the examples should be good enough.

    That said, if you wish to switch to the new pattern, there's a browserHistory module inside the router that you can access with

    import { browserHistory } from 'react-router'

    Now you have access to your browser history, so you can do things like push, replace, etc... Like:

    browserHistory.push('/some/path')

    Further reading: Histories and Navigation


    React-Router 1.x.x Answer

    I will not go into upgrading details. You can read about that in the Upgrade Guide

    The main change about the question here is the change from Navigation mixin to History. Now it's using the browser historyAPI to change route so we will use pushState() from now on.

    Here's an exemple using Mixin:

    var Example = React.createClass({
      mixins: [ History ],
      navigateToHelpPage () {
        this.history.pushState(null, `/help`);
      }
    })
    

    Note that this History comes from rackt/history project. Not from React-Router itself.

    If you don't want to use Mixin for some reason (maybe because of ES6 class), then you can access the history that you get from the router from this.props.history. It will be only accessible for the components rendered by your Router. So, if you want to use it in any child components it needs to be passed down as an attribute via props.

    You can read more about the new release at their 1.0.x documentation

    Here is a help page specifically about navigating outside your component

    It recommends grabbing a reference history = createHistory() and calling replaceState on that.

    React-Router 0.13.x Answer

    I got into the same problem and could only find the solution with the Navigation mixin that comes with react-router.

    Here's how I did it

    import React from 'react';
    import {Navigation} from 'react-router';
    
    let Authentication = React.createClass({
      mixins: [Navigation],
    
      handleClick(e) {
        e.preventDefault();
    
        this.transitionTo('/');
      },
    
      render(){
        return (<div onClick={this.handleClick}>Click me!</div>);
      }
    });
    

    I was able to call transitionTo() without the need to access .context

    Or you could try the fancy 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 (<div onClick={this.handleClick}>Click me!</div>);
      }
    }
    
    Authentication.contextTypes = {
      router: React.PropTypes.func.isRequired
    };
    

    React-Router-Redux

    Note: if you're using Redux, there is another project called React-Router-Redux that gives you redux bindings for ReactRouter, using somewhat the same approach that React-Redux does

    React-Router-Redux has a few methods available that allow for simple navigating from inside action creators. These can be particularly useful for people that have existing architecture in React Native, and they wish to utilize the same patterns in React Web with minimal boilerplate overhead.

    Explore the following methods:

    • push(location)
    • replace(location)
    • go(number)
    • goBack()
    • goForward()

    Here is an example usage, with Redux-Thunk:

    ./actioncreators.js

    import { goBack } from 'react-router-redux'
    
    export const onBackPress = () => (dispatch) => dispatch(goBack())
    

    ./viewcomponent.js

    <button
      disabled={submitting}
      className="cancel_button"
      onClick={(e) => {
        e.preventDefault()
        this.props.onBackPress()
      }}
    >
      CANCEL
    </button>
    
    0 讨论(0)
提交回复
热议问题