Search code examples
reactjstypescriptreduxreact-reduxjson-server

React-Redux componentWillReceiveProps not triggered using api data


I'm not sure if this is the correct way to do things, or if it's even possible, therefore my question here.

I'm using react-redux, redux-thunk, json-server (for dummy data) and typescript in my project. With 1 api call I update the 'data' reducer with all the data for my application. This data is used together with other reducers through combineReducers: Redux tree

What I'd like to do is map data.labels as prop into my component. Once the whole api call finishes, and data.labels is therefore filled, I would like to show this data to my front-end. I have however noticed that the componentWillReceiveProps is not triggered at all when my data api call is finished. It does update if I attach the whole 'data' prop to my component, instead of 'data.labels'.

Reducer:

    case Actions.RECEIVE:
        return {
            ...state,
            labels: action.payload.labels,
            defaultLinks: action.payload.defaultLinks,
            customLinks: action.payload.customLinks
        };

Component:

function mapStateToProps(state: any) {
return {
    labels: state.data.labels, // This will not trigger componentWillReceiveProps

function mapStateToProps(state: any) {
return {
    data: state.data, // This will trigger componentWillReceiveProps

Any tips on how to get this to work without injecting the whole data object as prop?

Edit

In the case of using te full 'data', I get an empty array of labels when logging data.labels in componentWillReceiveProps before the data has been fetched. After the data has been successfully fetched, my log shows an array of x amount of labels.

Below are the interfaces I use: Data interface (structure inside redux store, with 'data' as parent):

interface Data {
  labels: Label[];
  defaultLinks: DefaultLink[];
  customLinks: CustomLink[];
  request: boolean;
  failure: boolean;
}

Props interface used in my component:

interface Props {
  labels: Label[];
  ...; // Other stuff
}

Solution

  • You may be looking for the selector pattern: gist.github.com/abhiaiyer91/aaf6e325cf7fc5fd5ebc70192a1fa170 often used in combination with reselect: github.com/reactjs/reselect#reselect

    The primary advantage is you decouple the shape of your state from the shape of your props.