jcreamer898
jcreamer898

Reputation: 8189

How to transition routes after an ajax request in redux

I'm wondering at a high level what the correct pattern is for the following...

I have a HomeComponent, with some links to other components. When I click on one of the links, I want to make an ajax request to get the initial state for that component.

Do I dispatch in the HomeComponent in the onClick? Or dispatch an action in the other components if there's no initialState from the server? (I'm doing a universal app, so if I was to hit one of the other components directly, the initial state would already be there, but coming from my HomeComponent, the data WON'T be there)

This is what I had so far...

class HomeComponent extends React.Component {
  navigate(e) {
    e.preventDefault();

    // Fetch data here
    actions.fetch(1234);

    // When do I call this?
    browserHistory.push(e.target.href);
  }
  render() {
    const links = [
      <a href="/foo/1247462" onClick={this.navigate}>Link 1</a>,
      <a href="/foo/1534563">Link 2</a>,
    ];

    return (
      <ul>
        {links.map((link) => (
          <li>{link}</li>
        ))}
      </ul>
    );
  }
}

Upvotes: 3

Views: 799

Answers (1)

Mohamed Mellouki
Mohamed Mellouki

Reputation: 796

Sorry i can add a comment, is there a reason you're not using react-redux && redux-thunk ?

what you ask can be easily done with those : you fetch what you need in mapDispatchToProps & dispatch an action with the fetched initial state

Your reducer will catch the said dispatched action and update its state which will update the props of the react component with the help of mapStateToProps

I am writing from memory, it might not be accurate 100% :

redux file

componentNameReducer = (
    state = {
        history: ''
    },
    type = {}
) => {
    switch(action.type) {
        case 'HISTORY_FETCHED_SUCCESSFULLY':
            return Object.assign({}, state, {
                history: action.payload.history
            });
        default:
            return state;
    }
};

mapStateToProps = (state) => {
    history: state.PathToWhereYouMountedThecomponentNameReducerInTheStore.history
};

mapDispatchToProps = (dispatch) => ({
    fetchHistory : () => {
        fetch('url/history')
            .then((response) => {
                if (response.status > 400) {
                    disptach({
                        type: 'HISTORY_FETCH_FAILED',
                        payload: {
                            error: response._bodyText
                        }
                    });
                }
                return response;
            })
            .then((response) => response.json())
            .then((response) => {
                //do checkups & validation here if you want before dispatching
                dispatch({
                    type: 'HISTORY_FETCHED_SUCCESSFULLY',
                    payload: {
                        history: response
                    }
                });
            })
            .catch((error) => console.error(error));
    }
});

module.exports = {
    mapStateToProps,
    mapDispatchToProps,
    componentNameReducer
}

On your react component you will need :

import React, {
    Component    
} from 'somewhere';

import { mapStateToProps, mapDispatachToProps } from 'reduxFile';
import { connect } from 'react-redux';

class HistoryComponent extends Component {
    constructor(props){
        super(props);
        this.props.fetchHistory(); //this is provided by { connect } from react-redux
    }
    componentWillReceiveProps(nextProps){
        browserHistory.push(nextProps.history);
    }
    render() {
        return (

        );
    }
}
//proptypes here to make sure the component has the needed props

module.exports = connect(
    mapStateToProps,
    mapDispatachToProps
)(HistoryComponent);

Upvotes: 3

Related Questions