【问题标题】:force component to re-render after redux state change强制组件在 redux 状态更改后重新渲染
【发布时间】:2020-02-25 19:48:34
【问题描述】:

我有一个带有 2 个屏幕的堆栈导航器,“消息”和“消息”。在“消息”屏幕上,我想要了解与我聊天的所有人 + 对话中的最后一条消息的概览。我将所有对话存储在 redux 中,而不是在服务器上。我的 redux 状态如下所示:

const state = {
    user = [
        {
            userId: 1,
            username: John,
            messages: [...array of messages send to John or from John...]
        },
        {
            userId: 2,
            username: Jane,
            messages: [...array of messages send to Jane or from Jane...]
        }
        ...
    ]
}

在“消息”屏幕上,我有一个 FlatList 组件,它在 redux 状态下循环遍历 users-array:

const users = useSelector(state => state.messages.users)

const renderUserItem = user => {
    return (
        <View>
            <Text>{user.username}</Text>
            <Text>{user.messages[user.messages.length-1].message</Text>
        </View>
    )
}

<FlatList
    data={messages}
    renderItem={({item, index}) => renderUserItem(item)} />

这很有效,我可以大致了解我的对话 + 最后一条消息。当我单击“消息”屏幕上的对话时,我将被发送到“消息”屏幕,其中我有另一个 FlatList,其中包含此特定对话的所有消息。此代码无关紧要,但可以。

问题是:当我添加一条新消息(通过“消息”屏幕)时,redux 状态会更新:(dispatch(addMessage(userId, message)),但是当我导航回“消息”屏幕时,我没有'没有看到最后一条消息,即使 redux 状态发生了变化,屏幕也不会重新渲染。当我进行硬刷新时,它可以工作。

当 redux 状态发生变化时,如何强制重新渲染屏幕。我正在使用无状态组件。

编辑:我的减速器:

const initialState = {
    users: []
}

const MessagesReducer = (state = initialState, action) => {
    let array, index, user, messages
    switch (action.type) {
        case 'START_CONVERSATION':
            // action.user is an object which contains userId and username
            array = state.users
            index = array.findIndex(e => e.userId === action.user.userId)
            if (index > -1) {
                // conversation already exists
            } else {
            object = {
                userId: action.user.userId,
                username: action.user.username,
                messages: []
            }
            array.push(object)
            return {
                users: array
            }
        break
        case 'ADD_MESSAGE':
             // action.userId contains the userId of the conversation partner
             // action.message is an object with direction, 
             // message and timestamp in it
             array = state.users
             index = array.findIndex(e => e.userId === action.userId)
             user = array[index]
             user.messages.push({
                 direction: action.message.direction,
                 message: action.message.message,
                 timestamp: action.message.timestamp
             }
             // get the old user object out of the array
             array.splice(index, 1)
             // push the new user object to the beginning of the array
             array.unshift(user)  
             return {
                user: array
             }
        break
        default:
            return state
        break
    }
}

【问题讨论】:

  • 您不需要强制重新渲染,很可能还有其他问题。你能展示你的减速机吗?
  • 你能展示一下这个逻辑的减速器吗?
  • 我更新了我的问题

标签: reactjs react-native redux


【解决方案1】:

你正在改变状态,这使它看起来好像根本没有状态变化。这意味着无需重新渲染。

将此array = state.users 更改为array = [...state.users]

这将创建一个新的数组引用,而不是改变先前的状态,这将导致按预期重新渲染。


再看一遍,我发现了更多问题。这些不会停止重新渲染,但仍会改变以前的状态,因此应该修复它。

改变这个:

user = array[index] // user is still a reference to previous state
user.messages.push({ // messages is still a reference to previous state
  ...

到这里:

// Create a new user object based on the previous values
// Then add to the messages array by creating a new array with your new entry
user = {
  ...array[index], 
  messages: [
    ...array[index].messages, 
    {
      direction: action.message.direction,
      message: action.message.message,
      timestamp: action.message.timestamp
    }
  ]
}

// OR
user = {...array[index], messages: [...array[index].messages]}
user.messages.push({...})

【讨论】:

  • 太棒了!这是解决方案。非常感谢@Brian Thompson!
  • 不客气。误解 JavaScript 中的对象引用是错误的常见原因。我建议阅读该主题,它将在未来有很大帮助。至少它对我有用!
  • 如果我遇到像这样的新问题,我会尽量记住这一点。谢谢大佬!
  • 我强烈建议您使用our official Redux Toolkit package。它默认捕获突变并抛出错误以警告您。它还允许您使用“mutating”语法编写不可变的更新逻辑,这将大大简化 reducer。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
  • 2021-07-08
  • 1970-01-01
相关资源
最近更新 更多