Programmatically navigate using react router

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

    With the current React version (15.3), this.props.history.push('/location'); worked for me, but it showed the following warning:

    browser.js:49 Warning: [react-router] props.history and context.history are deprecated. Please use context.router.

    and I solved it using context.router like this:

    import React from 'react';
    
    class MyComponent extends React.Component {
    
        constructor(props) {
            super(props);
            this.backPressed = this.backPressed.bind(this);
        }
    
        backPressed() {
            this.context.router.push('/back-location');
        }
    
        ...
    }
    
    MyComponent.contextTypes = {
        router: React.PropTypes.object.isRequired
    };
    
    export default MyComponent;
    
    0 讨论(0)
  • 2020-11-21 05:22

    Update : React Router v6 with hooks

    import {useNavigate} from 'react-router-dom';
    let navigate = useNavigate();
    navigate('home');
    

    And to move across the browser history,

    navigate(-1); ---> Go back
    navigate(1);  ---> Go forward
    navigate(-2); ---> Move two steps backward.
    
    0 讨论(0)
  • 2020-11-21 05:23

    with React-Router v4 on the horizon, there is now a new way of doing this.

    import { MemoryRouter, BrowserRouter } from 'react-router';
    
    const navigator = global && global.navigator && global.navigator.userAgent;
    const hasWindow = typeof window !== 'undefined';
    const isBrowser = typeof navigator !== 'undefined' && navigator.indexOf('Node.js') === -1;
    const Router = isBrowser ? BrowserRouter : MemoryRouter;
    
    <Router location="/page-to-go-to"/>
    

    react-lego is an example app that shows how to use/update react-router and it includes example functional tests which navigate the app.

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

    Maybe not the best solution but it gets the job done:

    import { Link } from 'react-router-dom';
    
    // create functional component Post
    export default Post = () => (
        <div className="component post">
    
            <button className="button delete-post" onClick={() => {
                // ... delete post
                // then redirect, without page reload, by triggering a hidden Link
                document.querySelector('.trigger.go-home').click();
            }}>Delete Post</button>
    
            <Link to="/" className="trigger go-home hidden"></Link>
    
        </div>
    );
    

    Basically, a logic tied to one action (in this case a post deletion) will end up calling a trigger for redirect. This is not ideal because you will add a DOM node 'trigger' to your markup just so you can conveniently call it when needed. Also, you will directly interact with the DOM, which in a React component may not be desired.

    Still, this type of redirect is not required that often. So one or two extra, hidden links in your component markup would not hurt that much, especially if you give them meaningful names.

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

    This worked for me, no special imports needed:

    <input 
      type="button" 
      name="back" 
      id="back" 
      class="btn btn-primary" 
      value="Back" 
      onClick={() => { this.props.history.goBack() }} 
    />
    
    0 讨论(0)
  • 2020-11-21 05:23

    So in my answer there are 3 different ways to redirect programmatically to a route. Some of the solutions has been presented already but the following ones focused only for functional components with an additional demo application.

    Using the following versions:

    react: 16.13.1

    react-dom: 16.13.1

    react-router: 5.2.0

    react-router-dom: 5.2.0

    typescript: 3.7.2

    Configuration:

    So first of all the solution is using HashRouter, configured as follows:

    <HashRouter>
        // ... buttons for redirect
    
        <Switch>
          <Route exact path="/(|home)" children={Home} />
          <Route exact path="/usehistory" children={UseHistoryResult} />
          <Route exact path="/withrouter" children={WithRouterResult} />
          <Route exact path="/redirectpush" children={RedirectPushResult} />
          <Route children={Home} />
        </Switch>
    </HashRouter>
    

    From the documentation about <HashRouter>:

    A <Router> that uses the hash portion of the URL (i.e. window.location.hash) to keep your UI in sync with the URL.

    Solutions:

    1. Using <Redirect> to push using useState:

    Using in a functional component (RedirectPushAction component from my repository) we can use useState to handle redirect. Tricky part is once the redirection happened we need to set the redirect state back to false. By using setTimeOut with 0 delay we are waiting until React commits Redirect to the DOM then getting back the button in order to use next time.

    Please find my example below:

    const [redirect, setRedirect] = useState(false);
    const handleRedirect = useCallback(() => {
        let render = null;
        if (redirect) {
            render = <Redirect to="/redirectpush" push={true} />
            
            // in order wait until commiting to the DOM
            // and get back the button for clicking next time
            setTimeout(() => setRedirect(false), 0);
        }
        return render;
    }, [redirect]);
    
    return <>
        {handleRedirect()}
        <button onClick={() => setRedirect(true)}>
            Redirect push
        </button>
    </>
    

    From <Redirect> documentation:

    Rendering a <Redirect> will navigate to a new location. The new location will override the current location in the history stack, like server-side redirects (HTTP 3xx) do.

    1. Using useHistory hook:

    In my solution there is a component called UseHistoryAction which represents the following:

    let history = useHistory();
    
    return <button onClick={() => { history.push('/usehistory') }}>
        useHistory redirect
    </button>
    

    The useHistory hook gives us access to the history object which helps us programmatically navigate or change routes.

    1. Using withRouter, get the history from props:

    Created one component called WithRouterAction, displays as below:

    const WithRouterAction = (props:any) => {
        const { history } = props;
    
        return <button onClick={() => { history.push('/withrouter') }}>
            withRouter redirect
        </button>
    }
    
    export default withRouter(WithRouterAction);
    

    Reading from withRouter documentation:

    You can get access to the history object's properties and the closest <Route>'s match via the withRouter higher-order component. withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.

    Demo:

    For better representation I have built a GitHub repository with these examples, please find it below:

    https://github.com/norbitrial/react-router-programmatically-redirect-examples

    I hope this helps!

    0 讨论(0)
提交回复
热议问题