简体   繁体   English

嵌套 Map function 在使用 forceUpdate() 反应原生时不会更新 state

[英]Nested Map function doesnt update the state while using forceUpdate() in react native

I have a complex array filled the objects.(Shown below)我有一个复杂的数组填充对象。(如下所示)

 const privateMessages = Array [
  Object {
    "_id": "607533d511a2301b204720ed",
    "chat": Array [
      Object {
        "_id": "6098ffd30a2f4287f92be018",
        "createdAt": "2021-05-10T09:41:39.683Z",
        "text": "G",
        "user": Object {
          "_id": "60716a38136f970ba4a0526e",
        },
      },
      Object {
        "_id": "6097b6e69f98cbf5ba6deaf8",
        "createdAt": "2021-05-09T10:18:36.972Z",
        "text": "ত",
        "user": Object {
          "_id": "60716f7cf3a75846ee1f5d38",
        },
      },
      Object {
        "_id": "6097b6aacd62683ba317965d",
        "createdAt": "2021-05-09T10:17:36.182Z",
        "text": "H",
        "user": Object {
          "_id": "60716a38136f970ba4a0526e",
        },
      }
    ],
    "pair": Array [
      Object {
        "_id": "60716a38136f970ba4a0526e",
        "firstName": "Sayan",
        "lastName": "Biswas",
      },
    ],
  },
]

It is quite hard to update it using setState hook, so I decided to use force Update to re-render the component but its not working.使用 setState 钩子更新它非常困难,所以我决定使用强制更新来重新渲染组件,但它不起作用。 The way I am updating the state is given below下面给出了我更新 state 的方式

privateMessages.forEach((i) => {
                    if (i.pair[0]._id == data.sender) {
                        i.chat.unshift(data.chatObj)
                    }
                })

This is the forceUpdate hook I am using这是我正在使用的 forceUpdate 钩子

function useForceUpdate() {
    const [value, setValue] = useState(0); // integer state
    return () => setValue(value => value + 1); // update the state to force render
}

The way I am calling it我叫它的方式

const forceUpdate = useForceUpdate()

I am using the same forceUpdate() hook in the other part of my project and its working properly but I dont know why is it not working with the nested map function given below我在我的项目的另一部分使用相同的 forceUpdate() 钩子并且它工作正常,但我不知道为什么它不能与下面给出的嵌套 map function 一起工作

Edit:-编辑:-

Many of the answers told me not to use forceUpdate so I removed them.许多答案告诉我不要使用 forceUpdate 所以我删除了它们。 I tried all the solutions given in the answer but none of them is working.Getting idea from the answer of @Punisher, I made a solution myself of the state update part but the app crashes when it runs.我尝试了答案中给出的所有解决方案,但没有一个有效。从@Punisher 的答案中得到灵感,我自己制作了 state 更新部分的解决方案,但应用程序在运行时崩溃。

socket.on("recieve-private-message", (data) => {
                setPrivateMessages(prevState => {
                    const privateMessagesCopy = JSON.parse(JSON.stringify(prevState))
                    privateMessagesCopy.forEach((i) => {
                        if (i.pair[0]._id == data.sender) {
                            i.chat.unshift(data.chatObj)
                        }
                    })
                    return privateMessagesCopy
                }                    
                )
            })

The whole code:-整个代码: -

import React, { useState, useEffect, useContext } from 'react';
import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
import AsyncStorage from "@react-native-async-storage/async-storage"
import API from '../api.js'
import { useNavigation } from '@react-navigation/native';
import { SocketObj } from "./Main"

function useForceUpdate() {
    const [value, setValue] = useState(0); // integer state
    return () => setValue(value => value + 1); // update the state to force render
}

const ChatScreen = () => {

    const navigation = useNavigation()

    let socket = useContext(SocketObj)

    let [privateMessages, setPrivateMessages] = useState([])

    let [userId, setUserId] = useState('')

    const forceUpdate = useForceUpdate()

    useEffect(
        () => {
            const fetchData = async () => {
                try {
                    const response = await API.get('get/chats', {
                        headers: {
                            'Content-Type': 'application/json',
                            "auth-token": await AsyncStorage.getItem("token")
                        }
                    })
                    setPrivateMessages(response.data.chatFriends)
                    setUserId(response.data.userId)
                } catch (err) {
                    console.log(err.response)
                }
            }
            fetchData()

            socket.on("recieve-private-message", (data) => {
                privateMessages.forEach((i) => {
                    if (i.pair[0]._id == data.sender) {
                        i.chat.unshift(data.chatObj)
                    }
                })
                forceUpdate()
            })
        }, []
    )


    useEffect(
        () => {
            console.log("changed")
        },[privateMessages]
    )

    return (<View>
        <ScrollView >
            {
                privateMessages.map(
                    (i) => i.pair.map(
                        (j) => {
                            return (
                                <>
                                    <TouchableOpacity
                                        key={j._id}
                                        onPress={() => {
                                            navigation.navigate("PrivateConversation", {
                                                chats: i.chat,
                                                userId: userId,
                                                socket: socket,
                                                name: j.firstName,
                                                recieverId: j._id
                                            })
                                        }
                                        } >
                                        <Text key={j._id} >{j.firstName + ' ' + j.lastName}</Text>
                                    </TouchableOpacity>
                                </>
                            )
                        }
                    )
                )
            }
        </ScrollView>
    </View>)
}

export default ChatScreen

I think you are not updating state in your function我认为您没有在 function 中更新 state

Try something like below:-试试下面的东西: -

socket.on("recieve-private-message", (data) => {
  const privateMessagesCopy = [...privateMessages]
  const updatedPrivateMessages = privateMessagesCopy.map((i) => {
    if (i.pair[0]._id == data.sender) {
      i.chat.unshift(data.chatObj)
    }
    return i;
  })
  setPrivateMessage([...updatedPrivateMessages]);
})

I would avoid the force update pattern as much as possible.我会尽可能避免强制更新模式。 I don't think you need it here.我认为你在这里不需要它。 While I can't see anything glaringly wrong, I would recommend you try these two options to help debug.虽然我看不出有什么明显的错误,但我建议您尝试这两个选项来帮助调试。 If these solutions don't work, then there's something else very wrong.如果这些解决方案不起作用,那么还有其他一些非常错误的东西。

(1) Use setState instead. (1) 改用 setState。 When you update the chat object, create a deep copy of it first.当您更新聊天 object 时,首先创建它的深层副本。 Update the deep copy with your current method and then call setState(copy).使用当前方法更新深层副本,然后调用 setState(copy)。 Note: make sure to use a library to deep copy like lodash or the stringify trick ( What is the most efficient way to deep clone an object in JavaScript? )注意:确保使用库进行深度复制,如 lodash 或 stringify 技巧( 在 JavaScript 中深度克隆 object 的最有效方法是什么?

(2) Use reducers instead. (2) 改用reducer。 When you have complicated objects like yours, reducers are very commonly used.当你有像你这样复杂的对象时,reducers 是非常常用的。 This is probably the best solution in terms of best practices (maintainability and readability)就最佳实践(可维护性和可读性)而言,这可能是最佳解决方案

Change your socket function to:将您的插座 function 更改为:

socket.on("recieve-private-message", (data) => {
  setPrivateMessages(prevState => prevState
     .map(privateMessage => {
        const [firstPair] = privateMessage.pair

        return firstPair._id !== data.sender
            ? privateMessage
            : ({
                ...privateMessage,
                chat: [
                    data.chatObj,
                    ...privateMessage.chat
                ]
            })
     })
  )
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM