Programmatically navigate using react router

后端 未结 30 2304
無奈伤痛
無奈伤痛 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:24

    based on the previous answer
    from José Antonio Postigo and Ben Wheeler
    the novelty? is to be written in Typescript
    and the use of decorators
    OR static property/field

    import * as React from "react";
    import Component = React.Component;
    import { withRouter } from "react-router";
    
    export interface INavigatorProps {
        router?: ReactRouter.History.History;
    }
    
    /**
     * Note: goes great with mobx 
     * @inject("something") @withRouter @observer
     */
    @withRouter
    export class Navigator extends Component<INavigatorProps, {}>{
        navigate: (to: string) => void;
        constructor(props: INavigatorProps) {
            super(props);
            let self = this;
            this.navigate = (to) => self.props.router.push(to);
        }
        render() {
            return (
                <ul>
                    <li onClick={() => this.navigate("/home")}>
                        Home
                    </li>
                    <li onClick={() => this.navigate("/about")}>
                        About
                    </li>
                </ul>
            )
        }
    }
    
    /**
     * Non decorated 
     */
    export class Navigator2 extends Component<INavigatorProps, {}> {
    
        static contextTypes = {
            router: React.PropTypes.object.isRequired,
        };
    
        navigate: (to: string) => void;
        constructor(props: INavigatorProps, context: any) {
            super(props, context);
            let s = this;
            this.navigate = (to) =>
                s.context.router.push(to);
        }
        render() {
            return (
                <ul>
                    <li onClick={() => this.navigate("/home")}>
                        Home
                    </li>
                    <li onClick={() => this.navigate("/about")}>
                        About
                    </li>
                </ul>
            )
        }
    }
    

    with whatever npm installed today. "react-router": "^3.0.0" and
    "@types/react-router": "^2.0.41"

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

    React-Router v2

    For the most recent release (v2.0.0-rc5), the recommended navigation method is by directly pushing onto the history singleton. You can see that in action in the Navigating outside of Components doc.

    Relevant excerpt:

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

    If using the newer react-router API, you need to make use of the history from this.props when inside of components so:

    this.props.history.push('/some/path');
    

    It also offers pushState but that is deprecated per logged warnings.

    If using react-router-redux, it offers a push function you can dispatch like so:

    import { push } from 'react-router-redux';
    this.props.dispatch(push('/some/path'));
    

    However this may be only used to change the URL, not to actually navigate to the page.

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

    To use withRouter with a class-based component, try something like this below. Don't forget to change the export statement to use withRouter:

    import { withRouter } from 'react-router-dom'

    class YourClass extends React.Component {
      yourFunction = () => {
        doSomeAsyncAction(() =>
          this.props.history.push('/other_location')
        )
      }
    
      render() {
        return (
          <div>
            <Form onSubmit={ this.yourFunction } />
          </div>
        )
      }
    }
    
    export default withRouter(YourClass);
    
    0 讨论(0)
  • 2020-11-21 05:27

    Those who are facing issues in implementing this on react-router v4.

    Here is a working solution for navigating through the react app from redux actions.

    history.js

    import createHistory from 'history/createBrowserHistory'
    
    export default createHistory()
    

    App.js/Route.jsx

    import { Router, Route } from 'react-router-dom'
    import history from './history'
    ...
    <Router history={history}>
     <Route path="/test" component={Test}/>
    </Router>
    

    another_file.js OR redux file

    import history from './history' 
    
    history.push('/test') // this should change the url and re-render Test component
    

    All thanks to this comment: ReactTraining issues comment

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

    EDIT: React Router v6

    I haven't touched React in a while, but want to thank and highlight the comment below by @Shimrit Snapir

    on React-Router 6.0 <Redirect /> changed to <Navigate />

    React Router V4

    tl:dr;

    if (navigate) {
      return <Redirect to="/" push={true} />
    }
    

    The simple and declarative answer is that you need to use <Redirect to={URL} push={boolean} /> in combination with setState()

    push: boolean - when true, redirecting will push a new entry onto the history instead of replacing the current one.


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

    Full example here. Read more here.

    PS. The example uses ES7+ Property Initializers to initialise state. Look here as well, if you're interested.

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

    For React Router v4+

    Assuming that you won't be needing to navigate during the initial render itself (for which you can use <Redirect> component), this is what we are doing in our app.

    Define an empty route which returns null, this will allow you to get the access to the history object. You need to do this at the top level where your Router is defined.

    Now you can do all the things that can be done on history like history.push(), history.replace(), history.go(-1) etc!

    import React from 'react';
    import { HashRouter, Route } from 'react-router-dom';
    
    let routeHistory = null;
    
    export function navigateTo(path) {
      if(routeHistory !== null) {
        routeHistory.push(path);
      }
    }
    
    export default function App(props) {
      return (
        <HashRouter hashType="noslash">
          <Route
            render={({ history }) => {
              routeHistory = history;
              return null;
            }}
          />
          {/* Rest of the App */}
        </HashRouter>
      );
    }
    
    0 讨论(0)
提交回复
热议问题