React-Router: how to wait for an async action before route transition

后端 未结 2 1700
无人及你
无人及你 2020-12-15 07:02

Is it possible to call an async redux action known as a thunk on a particular route and not perform the transition until the response has succeeded or failed?

2条回答
  •  忘掉有多难
    2020-12-15 08:08

    First and foremost, I want to say that there is a debate around the topic of fetching data with react-router's onEnter hooks whether or not is good practice, nevertheless this is how something like that would go:

    You can pass the redux-store to your Router. Let the following be your Root component, where Router is mounted:

    ...
    import routes from 'routes-location';
    
    class Root extends React.Component {
      render() {
        const { store, history } = this.props;
    
        return (
          
            
              { routes(store) }
            
          
        );
      }
    }
    ...
    

    And your routes will be something like:

    import ...
    ...
    
    const fetchData = (store) => {
      return (nextState, transition, callback) => {
        const { dispatch, getState } = store;
        const { loaded } = getState().myCoolReduxStore;
        // loaded is a key from my store that I put true when data has loaded
    
        if (!loaded) {
          // no data, dispatch action to get it
          dispatch(getDataAction())
            .then((data) => {
              callback();
            })
            .catch((error) => {
              // maybe it failed because of 403 forbitten, we can use tranition to redirect.
              // what's in state will come as props to the component `/forbitten` will mount.
              transition({
                pathname: '/forbitten',
                state: { error: error }
              });
              callback();
            });
        } else {
          // we already have the data loaded, let router continue its transition to the route
          callback();
        }
      }
    };
    
    export default (store) => {
      return (
        
          
          
          
        
      );
    };
    

    Please notice that your router file is exporting a thunk with your store as argument, if you look upwards, see how we invoked the router, we pass the store object to it.

    Sadly, at the time of writing react-router docs return 404 to me, thus I cannot point you to the docs where (nextState, transition, callback) are described. But, about those, from my memory:

    • nextState describes the route react-router will transition to;

    • transition function to preform maybe another transition than the one from nextState;

    • callback will trigger your route transition to finish.

    Another think to point out is that with redux-thunk, your dispatch action can return a promise, check it in the docs here. You can find here a good example on how to configure your redux store with redux-thunk.

提交回复
热议问题