Search code examples
react-nativereduxreact-reduxreact-native-flatlistflatlist

react native FlatList not rerendering when data prop changes


I have a FlatList component that uses Redux (indirectly) as the source for the data prop. See below

 const mapStateToProps = state => ({
   rdx_activeUsers: state.profile.activeUsers,
 });
        
 convertRdxActiveUsersObjectToUsableArray = () => {
   let activeUsersArray = [];
   Object.values(this.props.rdx_activeUsers).forEach(userObj => {
       activeUsersArray.push(userObj);
   });
   return activeUsersArray;
 };
 //-----------------------------------------------------------------------
 render() {
    let usableArray4FlatList = this.convertRdxActiveUsersObjectToUsableArray();
    
    return (
      <View>
        <FlatList
          data={usableArray4FlatList}

Whenever an active user is added or removed in Firebase DB, I have listeners that increase or reduce the size of the Redux object rdx_activeUsers.......the goal is that this change in Redux should trigger the render() function (due to Redux being used in the convertRdxActiveUsersToUsableArray function....which is present in the render() function).

I can see via debugging tool that Redux rdx_activeUsers object is updating correctly whenever I add or remove a user....however the FlatList only rerenders dynamically when I add a user (i.e. the Redux object rdx_activeUsers increases in size)...but not when I remove one (i.e the Redux object rdx_activeUsers decreases in size).

I also tried adding prop extraData={this.props.rdx_activeUsers} ...but this didnt make any difference

UPDATE AS OF 12/31 Below are my reducers......
case ACTIVE_USER_CHILD_ADDED is successfully updating Redux AND triggering the rerender
case ACTIVE_USER_CHILD_REMOVED is successfully updating Redux BUT NOT triggering the rerender....looks like thats where the issue is

case ACTIVE_USER_CHILD_ADDED:
  const key2Add = action.payload.userId;
  const val2Add = action.payload;

  return { ...state, activeUsers: { ...state.activeUsers, [key2Add]: val2Add } };


case ACTIVE_USER_CHILD_CHANGED:
  const key2Updel = action.payload.userId;
  const val2Updel = action.payload;

   if (val2Updel.active) {
        return { ...state, activeUsers: { ...state.activeUsers,[key2Updel]: val2Updel } };
    }
  
  if (state.activeUsers) {
    const updatedstate = state;
    delete updatedstate.activeUsers[key2Updel];
    return {...updatedstate};
  }
  //else
  return state;

case ACTIVE_USER_CHILD_REMOVED:
  const key2Del = action.payload.userId;
  const oldState = state;
  delete oldState.activeMsgUsers[key2Del];
  return {...oldState};

Below shows my action creators

export const _actActiveUserChildAdded = userObj => {
  return {
    type: ACTIVE_USER_CHILD_ADDED,
    payload: userObj,
  };
};

export const _actActiveUserChildChanged = userObj => {
  return {
    type: ACTIVE_USER_CHILD_CHANGED,
    payload: userObj,
  };
};

export const _actActiveUserChildRemoved = userObj => {
  return {
    type: ACTIVE_USER_CHILD_REMOVED,
    payload: userObj,
  };
};

Solution

  • change case ACTIVE_USER_CHILD_REMOVED like following it should work, you are modifying the object which was mutating the state object instead of returning a new object.

    case ACTIVE_USER_CHILD_REMOVED:
      const key2Del = action.payload.userId;
      const {activeUsers:{[key2Del]:_,...restActiveUsers}} = state;
      return {...state,activeUsers:{...restActiveUsers}};