1

I'm new to react-native so please be kind. My reducer is updating but my component lifecycles are not getting triggered. I have a console.log() inside mapStateToProps function in the component which runs for all the store updates, but nothing is happening in the component

Snippet of my component

class CompaniesComponent extends React.Component {
state = {refreshing: false}
static getDerivedStateFromProps (props, state) {
    return {refreshing: props.data.loading};
}
onRefresh =() => {}
render () {
    return (
        <ScrollView bounces={false}  refreshControl={<RefreshControl title="Loading..." refreshing={this.props.data.loading} onRefresh={()=>this.onRefresh()} /> } >
            <Card>
                <CardItem header bordered>
                    <Icon active name="business" />
                    <Text>Companies</Text>
                </CardItem>
                <List>
                    {this.renderComponentItems()}
                </List>
            </Card> 
        </ScrollView>   
    )
}}

const mapStateToProps = (state) => {
console.log("myState", state);
let data = state.api.data[constants.analytics.resources.profile];
console.log(data);
return { data }}


const mapMethodsToProps = {retrieveData, setCompany }

export default connect(mapStateToProps, mapMethodsToProps)(CompaniesComponent);

My Reducer

const apiReducer = (state=initialState, action) => {
switch(action.type) {
    case actions.FETCH_DATA: {
        let copy = Object.assign({}, state);
        copy.data[action.payload.resource] = copy.data[action.payload.resource] || {};
        copy.data[action.payload.resource]['loading'] = true;
        return {
            ...copy    
        }
    }
    case actions.FETCH_DATA_FAILURE: {
        let copy = Object.assign({}, state);
        copy.data[action.payload.resource]['loading'] = false;
        copy.data[action.payload.resource]['error'] = action.payload.error;
        return {
            ...copy
        }
    }
    case actions.FETCH_DATA_SUCCESS: {
        let copy = Object.assign({},state);
        copy.data[action.payload.resource]['loading'] = false;
        copy.data[action.payload.resource]['data'] = action.payload.data;
        return {
            ...copy
        }
    }

    case actions.CLEAR_API_DATA: {
        return {
            ...initialState
        }
    }
    default: {
        return state;
    }
}}export default apiReducer;
T M
  • 516
  • 5
  • 18
  • 1
    Possible duplicate of [How to update a value of a nested object in a reducer?](https://stackoverflow.com/questions/40096036/how-to-update-a-value-of-a-nested-object-in-a-reducer) – Michael Cheng Jun 25 '19 at 19:26
  • 2
    You need to make copies of nested objects as well. See the Redux docs for [Updating Nested Objects](https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns#updating-nested-objects) for an explanation. Also note that you are needlessly making a copy of your `state` in your reducer twice - first via `Object.assign` and then again when you return `{ ...copy }`. – Michael Cheng Jun 25 '19 at 19:26
  • This is 100% the collect answer! Thanks for ending this all-day nightmare. !!!! – T M Jun 25 '19 at 21:52

1 Answers1

0

For those who stumble across this issue, see Michael Cheng's response in the comments. TLDR: each nested object in the reducer needs to be copied over into the new state

My reducer now looks like this ...

const apiReducer = (state=initialState, action) => {
switch(action.type) {
    case actions.FETCH_DATA: {
        return {
            ...state,
            data: {
                ...state.data,
                [action.payload.resource]: {
                    ...state.data[action.payload.resource],
                    loading: true
                }
            }    
        }
    }
    case actions.FETCH_DATA_FAILURE: {
        return {
            ...state,
            data: {
                ...state.data,
                [action.payload.resource]: {
                    ...state.data[action.payload.resource],
                    loading: false,
                    error: action.payload
                }
            }    
        }
    }
    case actions.FETCH_DATA_SUCCESS: {
        return {
            ...state,
            data: {
                ...state.data,
                [action.payload.resource]: {
                    ...state.data[action.payload.resource],
                    loading: false,
                    data: action.payload
                }
            }    
        }
    }

    case actions.CLEAR_API_DATA: {
        return {
            ...state,
            data: {
                ...state.data,
                [action.payload.resource]: {
                    ...state.data[action.payload.resource],
                    loading: false,
                    data: {}
                }
            }
        } 
    }
    default: {
        return state;
    }
}}
T M
  • 516
  • 5
  • 18