How to push to History in React Router v4?

后端 未结 21 1878
不思量自难忘°
不思量自难忘° 2020-11-22 00:27

In the current version of React Router (v3) I can accept a server response and use browserHistory.push to go to the appropriate response page. However, this isn

相关标签:
21条回答
  • 2020-11-22 01:10

    Simplest way in React Router 4 is to use

    this.props.history.push('/new/url');
    

    But to use this method, your existing component should have access to history object. We can get access by

    1. If your component is linked to Route directly, then your component already has access to history object.

      eg:

      <Route path="/profile" component={ViewProfile}/>
      

      Here ViewProfile has access to history.

    2. If not connected to Route directly.

      eg:

      <Route path="/users" render={() => <ViewUsers/>}
      

      Then we have to use withRouter, a heigher order fuction to warp the existing component.

      Inside ViewUsers component

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

      • export default withRouter(ViewUsers);

      That's it now, your ViewUsers component has access to history object.

    UPDATE

    2- in this scenario, pass all route props to your component, and then we can access this.props.history from the component even without a HOC

    eg:

    <Route path="/users" render={props => <ViewUsers {...props} />}
    
    0 讨论(0)
  • 2020-11-22 01:11

    If you want to use history while passing a function as a value to a Component's prop, with react-router 4 you can simply destructure the history prop in the render attribute of the <Route/> Component and then use history.push()

        <Route path='/create' render={({history}) => (
          <YourComponent
            YourProp={() => {
              this.YourClassMethod()
              history.push('/')
            }}>
          </YourComponent>
        )} />
    

    Note: For this to work you should wrap React Router's BrowserRouter Component around your root component (eg. which might be in index.js)

    0 讨论(0)
  • 2020-11-22 01:12

    so the way I do it is: - instead of redirecting using history.push, I just use Redirect component from react-router-dom When using this component you can just pass push=true, and it will take care of the rest

    import * as React from 'react';
    import { Redirect } from 'react-router-dom';
    class Example extends React.Component {
      componentDidMount() {
        this.setState({
          redirectTo: '/test/path'
        });
      }
    
      render() {
        const { redirectTo } = this.state;
    
        return <Redirect to={{pathname: redirectTo}} push={true}/>
      }
    }
    
    0 讨论(0)
  • 2020-11-22 01:13

    step one wrap your app in Router

    import { BrowserRouter as Router } from "react-router-dom";
    ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));
    

    Now my entire App will have access to BrowserRouter. Step two I import Route and then pass down those props. Probably in one of your main files.

    import { Route } from "react-router-dom";
    
    //lots of code here
    
    //somewhere in my render function
    
        <Route
          exact
          path="/" //put what your file path is here
          render={props => (
          <div>
            <NameOfComponent
              {...props} //this will pass down your match, history, location objects
            />
          </div>
          )}
        />
    

    Now if I run console.log(this.props) in my component js file that I should get something that looks like this

    {match: {…}, location: {…}, history: {…}, //other stuff }
    

    Step 2 I can access the history object to change my location

    //lots of code here relating to my whatever request I just ran delete, put so on
    
    this.props.history.push("/") // then put in whatever url you want to go to
    

    Also I'm just a coding bootcamp student, so I'm no expert, but I know you can also you use

    window.location = "/" //wherever you want to go
    

    Correct me if I'm wrong, but when I tested that out it reloaded the entire page which I thought defeated the entire point of using React.

    0 讨论(0)
  • 2020-11-22 01:14

    According to React Router v4 documentation - Redux Deep Integration session

    Deep integration is needed to:

    "be able to navigate by dispatching actions"

    However, they recommend this approach as an alternative to the "deep integration":

    "Rather than dispatching actions to navigate you can pass the history object provided to route components to your actions and navigate with it there."

    So you can wrap your component with the withRouter high order component:

    export default withRouter(connect(null, { actionCreatorName })(ReactComponent));

    which will pass the history API to props. So you can call the action creator passing the history as a param. For example, inside your ReactComponent:

    onClick={() => {
      this.props.actionCreatorName(
        this.props.history,
        otherParams
      );
    }}
    

    Then, inside your actions/index.js:

    export function actionCreatorName(history, param) {
      return dispatch => {
        dispatch({
          type: SOME_ACTION,
          payload: param.data
        });
        history.push("/path");
      };
    }
    
    0 讨论(0)
  • 2020-11-22 01:15

    I was able to accomplish this by using bind(). I wanted to click a button in index.jsx, post some data to the server, evaluate the response, and redirect to success.jsx. Here's how I worked that out...

    index.jsx:

    import React, { Component } from "react"
    import { postData } from "../../scripts/request"
    
    class Main extends Component {
        constructor(props) {
            super(props)
            this.handleClick = this.handleClick.bind(this)
            this.postData = postData.bind(this)
        }
    
        handleClick() {
            const data = {
                "first_name": "Test",
                "last_name": "Guy",
                "email": "test@test.com"
            }
    
            this.postData("person", data)
        }
    
        render() {
            return (
                <div className="Main">
                    <button onClick={this.handleClick}>Test Post</button>
                </div>
            )
        }
    }
    
    export default Main
    

    request.js:

    import { post } from "./fetch"
    
    export const postData = function(url, data) {
        // post is a fetch() in another script...
        post(url, data)
            .then((result) => {
                if (result.status === "ok") {
                    this.props.history.push("/success")
                }
            })
    }
    

    success.jsx:

    import React from "react"
    
    const Success = () => {
        return (
            <div className="Success">
                Hey cool, got it.
            </div>
        )
    }
    
    export default Success
    

    So by binding this to postData in index.jsx, I was able to access this.props.history in request.js... then I can reuse this function in different components, just have to make sure I remember to include this.postData = postData.bind(this) in the constructor().

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