![](/img/trans.png)
[英]MapBox dosn't change renderAnnoations when update state in react native ( setState(..) , forceUpdate() have no effect to it )
[英]Nested Map function doesnt update the state while using forceUpdate() in react native
我有一个复杂的数组填充对象。(如下所示)
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",
},
],
},
]
使用 setState 钩子更新它非常困难,所以我决定使用强制更新来重新渲染组件,但它不起作用。 下面给出了我更新 state 的方式
privateMessages.forEach((i) => {
if (i.pair[0]._id == data.sender) {
i.chat.unshift(data.chatObj)
}
})
这是我正在使用的 forceUpdate 钩子
function useForceUpdate() {
const [value, setValue] = useState(0); // integer state
return () => setValue(value => value + 1); // update the state to force render
}
我叫它的方式
const forceUpdate = useForceUpdate()
我在我的项目的另一部分使用相同的 forceUpdate() 钩子并且它工作正常,但我不知道为什么它不能与下面给出的嵌套 map function 一起工作
编辑:-
许多答案告诉我不要使用 forceUpdate 所以我删除了它们。 我尝试了答案中给出的所有解决方案,但没有一个有效。从@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
}
)
})
整个代码: -
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
我认为您没有在 function 中更新 state
试试下面的东西: -
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]);
})
我会尽可能避免强制更新模式。 我认为你在这里不需要它。 虽然我看不出有什么明显的错误,但我建议您尝试这两个选项来帮助调试。 如果这些解决方案不起作用,那么还有其他一些非常错误的东西。
(1) 改用 setState。 当您更新聊天 object 时,首先创建它的深层副本。 使用当前方法更新深层副本,然后调用 setState(copy)。 注意:确保使用库进行深度复制,如 lodash 或 stringify 技巧( 在 JavaScript 中深度克隆 object 的最有效方法是什么? )
(2) 改用reducer。 当你有像你这样复杂的对象时,reducers 是非常常用的。 就最佳实践(可维护性和可读性)而言,这可能是最佳解决方案
将您的插座 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.