Should i fetch data in react component or redux action?

Your components will be primarily used to dispatch actions and display returned data. You will trigger the API call in the component with a dispatched action, and handle the response within the reducer. This is usually done with something like redux-thunk or redux-sagas to handle the async actions, then you can access the data you have called from your redux state. I'm personally a fan of redux-saga, you can check that out here

Redux-Saga


1. Fetch data in react component and pass data to redux action - NO (dispatch api action in the component)

2. Fetch data inside of redux action - NO (dispatch API promise here)

Trigger an action to call the api(async action) and handle the response in a reducer.

The action can be triggered inside your component.

If the component is going to consume this data, connect it to the global state(redux) using the HOC function connect


The general rule of thumb is:

  • If your data is only going to be used inside an individual component, then you should keep it there.
  • If your data will be used in other components, keep it in the parent or global state (redux in this case).

However there's a catch. Depending on the load order of your components, you might benefit from making the api call before your component is loaded, in which case, fetching your data from the redux action would be useful.

E.g. If you have to click to load a component, and then it will trigger the api call, you might benefit from simply loading it in the background before the user clicks, to make better use of their bandwidth during possible downtime.


If you are dead set on using Redux then you would obviously want to handle it by using an action.

Generally if the data is only used in a component then it would be fine to do the API call in componentDidUpdate() or on an event.

If the data is going to be used by a bunch of unrelated components or you end up doing a lot of prop threading then you would want to use Redux.

actions/index.js

  export const FETCH_DATA = 'FETCH_DATA'

  export const fetchData = async () => {

    const url = `http://your-url.com`;
    const request = await fetch(url);

    return {
      type: FETCH_DATA,
      payload: request
    }
  }

Then consumer the data you got from your action in a reducer.

reducers/reducer_whatever.js

  import { FETCH_DATA } from '../actions/index'

  export default function(state = [], action) {
    switch (action.type) {
      case FETCH_SOMETHING:
      return [ action.payload.data, ...state ];
    }

    return state;
  }