React Native Flatlist不重新呈现Redux

问题描述 投票:0回答:2

当我从redux传递的道具更改时,我的FlatList不会更新。每当我发送一条消息时,我都会在Firebase和Redux存储中增加每个人的未读消息数。我确保包括密钥提取器和额外的数据,但都无济于事。唯一改变未读消息计数的是重新加载设备。如何确保flatList使用MapStateToProps更新。我确保使用Object.Assign创建一个新对象:

动作:

export const sendMessage = (
  message,
  currentChannel,
  channelType,
  messageType
) => {
  return dispatch => {
    dispatch(chatMessageLoading());
    const currentUserID = firebaseService.auth().currentUser.uid;
    let createdAt = firebase.database.ServerValue.TIMESTAMP;
    let chatMessage = {
      text: message,
      createdAt: createdAt,
      userId: currentUserID,
      messageType: messageType
    };


    FIREBASE_REF_MESSAGES.child(channelType)
      .child(currentChannel)
      .push(chatMessage, error => {
        if (error) {
          dispatch(chatMessageError(error.message));
        } else {
          dispatch(chatMessageSuccess());
        }
      });

    const UNREAD_MESSAGES = FIREBASE_REF_UNREAD.child(channelType)
      .child(currentChannel).child('users')

    UNREAD_MESSAGES.once("value")
      .then(snapshot => {
        snapshot.forEach(user => {
          let userKey = user.key;
          // update unread messages count
          if (userKey !== currentUserID) {
            UNREAD_MESSAGES.child(userKey).transaction(function (unreadMessages) {
              if (unreadMessages === null) {
                dispatch(unreadMessageCount(currentChannel, 1))
                return 1;
              } else {
                alert(unreadMessages)
                dispatch(unreadMessageCount(currentChannel, unreadMessages + 1))
                return unreadMessages + 1;
              }
            });
          } else {
            UNREAD_MESSAGES.child(userKey).transaction(function () {
              dispatch(unreadMessageCount(currentChannel, 0))
              return 0;
            });
          }
        }
        )
      })
  };
};

export const getUserPublicChannels = () => {
  return (dispatch, state) => {
    dispatch(loadPublicChannels());
    let currentUserID = firebaseService.auth().currentUser.uid;
    // get all mountains within distance specified
    let mountainsInRange = state().session.mountainsInRange;
    // get the user selected mountain
    let selectedMountain = state().session.selectedMountain;

    // see if the selected mountain is in range to add on additional channels
    let currentMountain;
    mountainsInRange
      ? (currentMountain =
        mountainsInRange.filter(mountain => mountain.id === selectedMountain)
          .length === 1
          ? true
          : false)
      : (currentMountain = false);

    // mountain public channels (don't need to be within distance)
    let currentMountainPublicChannelsRef = FIREBASE_REF_CHANNEL_INFO.child(
      "Public"
    )
      .child(`${selectedMountain}`)
      .child("Public");

    // mountain private channels- only can see if within range
    let currentMountainPrivateChannelsRef = FIREBASE_REF_CHANNEL_INFO.child(
      "Public"
    )
      .child(`${selectedMountain}`)
      .child("Private");

    // get public channels
    return currentMountainPublicChannelsRef
      .orderByChild("key")
      .once("value")
      .then(snapshot => {
        let publicChannelsToDownload = [];

        snapshot.forEach(channelSnapshot => {
          let channelId = channelSnapshot.key;
          let channelInfo = channelSnapshot.val();
          // add the channel ID to the download list

          const UNREAD_MESSAGES = FIREBASE_REF_UNREAD.child("Public")
            .child(channelId).child('users').child(currentUserID)
          UNREAD_MESSAGES.on("value",snapshot => {
              if (snapshot.val() === null) {
                // get number of messages in thread if haven't opened
                dispatch(unreadMessageCount(channelId, 0));
              } else {
                dispatch(unreadMessageCount(channelId, snapshot.val()));
              }
            }
            )
          publicChannelsToDownload.push({ id: channelId, info: channelInfo });
        });

        // flag whether you can check in or not
        if (currentMountain) {
          dispatch(checkInAvailable());
        } else {
          dispatch(checkInNotAvailable());
        }

        // if mountain exists then get private channels/ if in range
        if (currentMountain) {
          currentMountainPrivateChannelsRef
            .orderByChild("key")
            .on("value", snapshot => {
              snapshot.forEach(channelSnapshot => {
                let channelId = channelSnapshot.key;
                let channelInfo = channelSnapshot.val();


                const UNREAD_MESSAGES = FIREBASE_REF_UNREAD.child("Public")
                  .child(channelId).child('users').child(currentUserID)
                UNREAD_MESSAGES.on("value",
                  snapshot => {
                    if (snapshot.val() === null) {
                      // get number of messages in thread if haven't opened
                      dispatch(unreadMessageCount(channelId, 0));
                    } else {
                     dispatch(unreadMessageCount(channelId, snapshot.val()));
                    }
                  }
                  )
                publicChannelsToDownload.push({ id: channelId, info: channelInfo });
              });
            });
        }
        return publicChannelsToDownload;
      })

      .then(data => {
        setTimeout(function () {
          dispatch(loadPublicChannelsSuccess(data));
        }, 150);
      });
  };
};

减速器:

case types.UNREAD_MESSAGE_SUCCESS:
        const um = Object.assign(state.unreadMessages, {[action.info]: action.unreadMessages});
    return {
      ...state,
      unreadMessages: um
    };

Container-内部,我将地图状态与未读消息关联到prop,然后作为prop传递给我的组件:

const mapStateToProps = state => {
return {
  publicChannels: state.chat.publicChannels,
  unreadMessages: state.chat.unreadMessages,
};
}

Component:

render() {
    // rendering all public channels
    const renderPublicChannels = ({ item, unreadMessages }) => {
      return (
        <ListItem
          title={item.info.Name}
          titleStyle={styles.title}
          rightTitle={(this.props.unreadMessages || {} )[item.id] > 0 && `${(this.props.unreadMessages || {} )[item.id]}`}
          rightTitleStyle={styles.rightTitle}
          rightSubtitleStyle={styles.rightSubtitle}
          rightSubtitle={(this.props.unreadMessages || {} )[item.id] > 0 && "unread"}
          chevron={true}
          bottomDivider={true}
          id={item.Name}
          containerStyle={styles.listItemStyle}
        />
      );
    };


    return (
        <View style={styles.channelList}>
          <FlatList
            data={this.props.publicChannels}
            renderItem={renderPublicChannels}
            keyExtractor={(item, index) => index.toString()}
            extraData={[this.props.publicChannels, this.props.unreadMessages]}
            removeClippedSubviews={false}
          />
        </View>
    );
  }
}
javascript react-native chat react-native-flatlist listitem
2个回答
0
投票

Object.assign()不返回新对象。因此,在缩减程序中,unreadMessages指向相同的对象,并且组件未重新呈现。

在减速机中使用]

const um = Object.assign({}, state.unreadMessages, {[action.info]: action.unreadMessages});

0
投票

Object.assign将所有内容合并到作为参数提供的第一个对象中,并返回相同的对象。在redux中,您需要创建一个新的对象引用,否则不能保证可以接受更改。使用此

© www.soinside.com 2019 - 2024. All rights reserved.