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. The way I am updating the state is given below
privateMessages.forEach((i) => {
if (i.pair[0]._id == data.sender) {
i.chat.unshift(data.chatObj)
}
})
This is the forceUpdate hook I am using
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
Edit :-
Many of the answers told me not to use forceUpdate so I removed them . 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.
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