当数据属性更改时,本机 FlatList 不会重新渲染

react native FlatList not rerendering when data prop changes

我有一个 FlatList 组件,它使用 Redux(间接)作为 data 道具的来源。见下文

 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}

每当在 Firebase DB 中添加或删除活动用户时,我都会有增加或减少 Redux 对象大小的侦听器 rdx_activeUsers.......目标是 Redux 中的此更改应该触发 render() 函数(由于在 convertRdxActiveUsersToUsableArray 函数中使用了 Redux....它存在于 render() 函数中)。

我可以通过调试工具看到,每当我添加或删除用户时,Redux rdx_activeUsers 对象 都会正确更新...但是 FlatList 仅在我 添加 用户时动态重新呈现(即 Redux 对象 rdx_activeUsers 大小增加)...但当我 删除 一个(即 Redux 对象 rdx_activeUsers 减小大小)。

我也试过添加 prop extraData={this.props.rdx_activeUsers} ...但这没有任何区别

12 月 31 日更新 下面是我的减速器......
case ACTIVE_USER_CHILD_ADDED 正在成功更新 Redux AND 触发重新渲染
case ACTIVE_USER_CHILD_REMOVED 正在成功更新 Redux 但不会 触发重新渲染....看起来问题就出在这里

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};

下面是我的动作创作者

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,
  };
};

试试这个

const mapStateToProps = state => ({
   rdx_activeUsers: state.profile.activeUsers,
 });
        

 //-----------------------------------------------------------------------
 render() {
    let activeUsersArray = [];
   Object.values(this.props.rdx_activeUsers).forEach(userObj => {
       activeUsersArray.push(userObj);
   });
    
    return (
      <View>
        <FlatList
          data={activeUsersArray}

这段代码不会触发重新渲染

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

通过返回 {...oldState}this.state 中的所有引用保持不变,不会触发更新

快速解决

return {...oldState, activeMsgUsers: {...activeMsgUsers}}代替

更好的解决方案

不要使用 delete,而是使用 Array.filter 来创建新的对象引用

最佳解决方案

将您的组件重构为挂钩并使 activeMsgUsers 成为独立状态,如果您正确执行,调用 setActiveMsgUsers 返回解构的旧状态,您就不会遇到这个问题

更改大小写 ACTIVE_USER_CHILD_REMOVED 就像遵循它应该工作一样,您正在修改正在改变状态对象而不是返回新对象的对象。

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