Component not re-rendering , after reducer call and props not updating?

You misunderstand how the pieces are supposed to fit together here. I highly recommend that you read the redux best practices and learn more about what a reducer does and does not do. A redux reducer should not perform any actions. It merely takes the current state and returns the next state based on the data in an action object.

Luckily you are already using redux-saga, which is designed to handle side-effects such as API calls. The fetch needs to be executed in your saga, not in the reducer.

An API call typically involves dispatching three actions: start, success, and failure. From your component, you would only ever dispatch the “FETCH_STOCKS_START” action. The saga “takes” this action via takeLatest and uses it to execute the fetch with its call effect. When the fetch is finished, the saga uses put to dispatch one of two result actions. It sends either type “FETCH_STOCKS_SUCCESS” with a property payload containing an array of stocks, or type “FETCH_STOCKS_ERROR” with a property error containing the error.

function* fetchStockData() {
  yield delay(4000);
  try {
    const res = yield call( axios.get, `http://api.marketstack.com/v1/eod/latest?access_key=8c21347ee7c5907b59d3cf0c8712e587&symbols=TCS.XBOM`);
    yield put({ type: "FETCH_STOCKS_SUCCESS", payload: res.data });
  }
  catch (error) {
    yield put({ type: "FETCH_STOCKS_ERROR", error });
  }
}

function* watchfetchStockData() {
  yield takeLatest("FETCH_STOCKS_START", fetchStockData);
}

Relevant saga docs links: Error Handling and Dispatching Actions

I have added an isLoading property to the state, which you can select to show a different UI when true. We will update this property with all three actions.

const initialState = {
  stocks: [],
  isLoading: false
};

Your reducer serves only to update the raw data in the state based on these actions.

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "FETCH_STOCKS_START":
      return {
        ...state,
        isLoading: true
      };
    case "FETCH_STOCKS_ERROR":
      console.error(action.error); // only temporary since you aren't doing anything else with it
      return {
        ...state,
        isLoading: false
      };
    case "FETCH_STOCKS_SUCCESS":
      return {
        ...state,
        stocks: action.payload,
        isLoading: false
      };
    default:
      return state;
  }
};

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top