React批处理来自不同用途的状态更新效果



在下面的代码快照中,useEffects中调用了5个不同的状态更新;第一组3个,第二组2个。

我记录了我的代码,发现屏幕只渲染了3次,所以有1次初始渲染和2次附加渲染。

有趣的是,如果我注释掉/删除整个第二个useEffect,我仍然会得到3个渲染,所以没有什么变化。这让我相信,来自不同useEffects的状态更新可以批量处理在一起?

我也有点困惑,为什么我没有得到6个渲染(1个初始渲染+5个更新(,因为我所有的状态更新调用都在.then Promise中。我在网上读到的是,在例如事件处理程序代码中,更新是分批进行的,但在Promise的情况下不是这样。。。https://blog.logrocket.com/simplifying-state-management-in-react-apps-with-batched-updates/#:~:text=按%20默认%2C%20React%20批次%20更新,时间%20调用%20是%20made。

useEffect 1状态更新:

setChatsToDisplay(chats)
setChatsUsersInfo(chatsWithUsersInfo)
setChatsAreInitializing(false)

UseEffect 2状态更新:

setMatchInvites(data)
setMatchInvitesAreInitializing(false)

调用这些更新的完整代码:

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)
})
}, [])

如果所有这些setState方法都来自useState调用,我实际上会尝试使用https://reactjs.org/docs/hooks-reference.html#usereducer.在此进行一些讨论:https://stackoverflow.com/a/64942458/14953263

这使您能够以更平滑的方式处理复杂状态,避免所有这些批量更新和潜在的奇怪行为。

reducer允许您更新来自redux的操作,但有一个更轻量级的API,允许您将其用于某些组件

状态更新是异步的,通常是分批进行的,我认为它们是否有单独的副作用并不重要。

最新更新