Roman Ventskus
Roman Ventskus

Reputation: 50

Where should I load data from server in Redux + ReactJS?

For example I have two components - ListOfGroupsPage and GroupPage.

In ListOfGroupsPage I load list of groups from the server and store it to the state.groups

In route I have mapping like ‘group/:id’ for GroupPage

When this address is loaded, the app shows GroupPage, and here I get the data for group from state.groups (try to find group in state via id). All works fine.

But if I reload page, I'm still on page /group/2, so GroupPage is shown. But state is empty, so the app can't find the group.

What is the proper way to load data in React + Redux? I can see this ways:

1) Load all data in root component. It will be very big overhead from traffic side

2) Don't rely on store, try to load required data on each component. It's more safe way. But I don't think that load the same data for each component - it's cool idea. Then we don't need the state - because each component will fetch the data from server

3) ??? Probably add some kind of checking in each component - first try to find required data in store. If can't - load from the server. But it requires much of logic in each component.

So, is there the best solution to fetch data from server in case of usage Redux + ReactJS?

Upvotes: 2

Views: 1572

Answers (3)

jpdelatorre
jpdelatorre

Reputation: 3593

One approach to this is to use redux-thunk to check if the data exist in the redux store and if not, send a server request to load the missing info.

Your GroupPage component will look something like

class GroupPage extends Component {
  componentWillMount() {
    const groupId = this.props.params.groupId
    this.props.loadGroupPage(groupId);
  }
  ...
}

And in your action...

const loadGroupPage = (groupId) => (dispatch, getState) => {
  // check if data is in redux store
  // assuming your state.groups is object with ids as property
  const {
    groups: {
      [groupId]: groupPageData = false
    }
  } = getState();

  if (!groupPageData) {
    //fetch data from the server
    dispatch(...)
  }
}

Upvotes: 2

patrick
patrick

Reputation: 10273

The way I approach this is to fetch from the server straight after the store has been created. I do this by dispatching actions. I also use thunks to set isFetching = true upon a *_REQUEST and set that back to false after a *_SUCCESS or *_FAILURE. This allows me to display the user things like a progress bar or spinner. I think you're probably overestimating the 'traffic' issue because it will be executed asynchronosly as long as you structure your components in a way that won't break if that particular part of the store is empty.

The issue you're seeing of "can't get groups of undefined" (you mentioned in a comment) is probably because you've got an object and are doing .groups on it. That object is most likely empty because it hasn't been populated. There are couple of things to consider here:

  • Using ternary operators in your components to check that someObject.groups isn't null; or
  • Detailing in the initialState for someObject.groups to be an empty array. That way if you were to do .map it would not error.
  • Use selectors to retrieve the list of groups and if someObject.groups is null return an empty array.

You can see an example of how I did this in a small test app. Have a look at specifically:

  • /src/index.js for the initial dispatch
  • /src/redux/modules/characters.js for the use of thunks
  • /src/redux/selectors/characters.js for the population of the comics, series, etc. which are used in the CharacterDetails component

Upvotes: 0

Ezra Chang
Ezra Chang

Reputation: 1298

I recommend caching the information on the client using localstorage. Persist your Redux state, or important parts of it, to localstorage on state change, and check for existing records in localstorage on load. Since the data would be on the client, it would be simple and quick to retrieve.

Upvotes: 0

Related Questions