In the below code snapshot, there are 5 different state updates called in useEffects; 3 in the first and 2 in the second.
I log my code and see that the screen has only rendered 3 times, so 1 initial render and 2 additional renders.
Interestingly, if I comment out / remove the entire second useEffect, I still get 3 renders, so nothing changes. This leads me to believe that state updates from different useEffects can be batched together?
I am also a little confused why I don't get 6 renders instead (1 initial render + 5 updates), because all my state update calls are in a .then Promise. What I read online is that in e.g. event handler code the updates are batched together but not in case of Promise... https://blog.logrocket.com/simplifying-state-management-in-react-apps-with-batched-updates/#:~:text=By%20default%2C%20React%20batches%20updates,time%20the%20call%20is%20made.
useEffect 1 state updates:
setChatsToDisplay(chats)
setChatsUsersInfo(chatsWithUsersInfo)
setChatsAreInitializing(false)
UseEffect 2 state updates:
setMatchInvites(data)
setMatchInvitesAreInitializing(false)
Full code where these updates are called:
useEffect(() => {
getUserChats(userId)
.then((getUserChatsData) => {
if (getUserChatsData) {
const chats = {}
for (i = 0; i < getUserChatsData.length; i++) {
const matchedUserInArrayFormat = getUserChatsData[i]['users'].filter((users) => {
return users !== userId
})
const matchedUser = matchedUserInArrayFormat[0]
const message = getUserChatsData[i]['message'][0]['content']
chats[matchedUser] = message
}
const matchedChatUserIds = getUserChatsData.map(userChat => {
const arrayWithMatchedChatUserId = userChat['users'].filter((users) => {
return users !== userId
})
return arrayWithMatchedChatUserId[0]
})
getUserInfo(matchedChatUserIds, JSON.stringify({'name': 1, 'userId': 1, 'profilePictureURI' : 1}), 10)
.then((userInfo) => {
var chatsWithUsersInfo = userInfo.map((user, index) => (
{'index': index, 'matchedUserId': user.userId, 'matchedUserProfilePictureURI': user.profilePictureURI, 'matchedUserName': user.name}
))
// Updating the states in this order below appears to render the screen two times with the same chatsToDisplay value, which is required to get previousChatsToDisplay to use the initially retrieved chats as base (not an empty Object). The useEffect that depends on [chatsToDisplay, chatsAreInitializing] can then effectively compare new chats
setChatsToDisplay(chats)
setChatsUsersInfo(chatsWithUsersInfo)
console.log('gonna set to false');
setChatsAreInitializing(false)
})
}
})
}, [])
useEffect(() => {
getMatchInvites(userId, 10)
.then((getMatchInvitesData) => {
const data = getMatchInvitesData.map((match, index) => (
{'index': index, 'matchedUserId': match['usersInfo'][0]['userId'], 'matchType': match['matchType'], 'matchedUserRating': match['usersInfo'][0]['rating'], 'matchId': match['_id']}
))
setMatchInvites(data)
// To-do: Check my logic for this screen and how it holds with this included
setMatchInvitesAreInitializing(false)
})
}, [])
question from:
https://stackoverflow.com/questions/65598773/react-batches-state-updates-from-different-useeffects 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…