即使在状态更改后组件也不会更新
Posted
技术标签:
【中文标题】即使在状态更改后组件也不会更新【英文标题】:Component not updating even after state is changed 【发布时间】:2021-07-26 12:57:39 【问题描述】:我有这个朋友组件,我在数据库中搜索用户的朋友(存储在用逗号分隔的字符串中)并将它们显示在可滚动的 div 中。您还可以添加新朋友。数据库和后端一切正常。但是,当状态改变时,组件不会被重新渲染。它依赖于“allFriends”,因此它应该在更新时重新渲染。你们知道这里发生了什么吗?我猜它与异步性有关,但我似乎无法确定它。我为每个代码块添加了注释,以使其更易于阅读。
import React, useState, useEffect from 'react';
import SingleFriend from './SingleFriend';
import './friends.css';
const Friends = (username) =>
const [allFriends, setAllFriends] = useState([]);
const [unsortedFriends, setUnsortedFriends] = useState([]);
const [friendFilter, setFriendFilter] = useState('');
const [friendSearch, setFriendSearch] = useState('');
//-----------------------------------------------------------------------------------
// Start fetching friends on component mount
//-----------------------------------------------------------------------------------
useEffect(() =>
fetchFriends();
, [])
//-----------------------------------------------------------------------------------
// Sort the friends when fetching has finished/unsortedFriends has updated
//-----------------------------------------------------------------------------------
useEffect(() =>
const onlineFriends = [];
const offlineFriends = [];
unsortedFriends.forEach(f =>
if (f.status === 'online')
onlineFriends.push(f)
else
offlineFriends.push(f)
)
setAllFriends(onlineFriends.concat(offlineFriends));
,[unsortedFriends])
//-----------------------------------------------------------------------------------
// Get the string of friends that is stored in the database for the user
// Convert to array of friends
// Pass the array to 'fetchFriendData()'
//-----------------------------------------------------------------------------------
const fetchFriends = () =>
let allFriendNames = [];
fetch(`http://localhost:8000/getFriends?username=$username`)
.then(res => res.json())
.then(friends =>
if (friends !== null && friends !== '')
allFriendNames = friends.split(',');
fetchFriendData(allFriendNames);
)
//-----------------------------------------------------------------------------------
// Search the database for each of the user's friends
// Return those users, and add their username & online status to a temporary array
// Assign that array to the unsortedFriends useState hook
//-----------------------------------------------------------------------------------
const fetchFriendData = (allFriendNames) =>
let allF = [];
for (let friend of allFriendNames)
fetch(`http://localhost:8000/findFriend?username=$friend`)
.then(res => res.json())
.then(user =>
if (user.socketid)
allF.push(name: user.username, status: 'online')
else
allF.push(name: user.username, status: 'offline')
)
.catch(err => console.log(err))
document.querySelector('.addFriendInput').value = '';
setUnsortedFriends(allF);
//-----------------------------------------------------------------------------------
// Called on button press to add friend
//-----------------------------------------------------------------------------------
const addFriend = () =>
let friendList = '';
let friendArray = [];
//-----------------------------------------------------------------------------------
// Search the database to check if the name that was
// entered matches any users in the databse
//-----------------------------------------------------------------------------------
fetch(`http://localhost:8000/findFriend?username=$friendSearch`)
.then(res => res.json())
.then(user =>
if (user.username)
//-----------------------------------------------------------------------------------
// If friend exists, grab the user's friend list string
// Make a temporary string and array with the new friend
//-----------------------------------------------------------------------------------
fetch(`http://localhost:8000/getFriends?username=$username`)
.then(res => res.json())
.then(friends =>
if (friends !== null && friends !== '')
friendArray = friends.split(',');
if (friendArray.includes(friendSearch))
throw new Error('Problem getting friend')
else
friendArray.push(friendSearch);
friendList = friends.concat(`,$friendSearch`);
else
friendList = friendSearch;
friendArray = [friends];
//-----------------------------------------------------------------------------------
// Update the user's friend list with the new friends string
// Pass the updated friends array to 'fetchFriendData'
//-----------------------------------------------------------------------------------
fetch('http://localhost:8000/addFriend',
method: 'put',
headers: 'Content-Type': 'application/json',
body: JSON.stringify(
username: username,
friendlist: friendList
)
)
.then(fetchFriendData(friendArray))
.catch(err => console.log(err))
)
.catch(err => console.log(err))
)
.catch(err => console.log(err))
return (
<div className='friendsContainer'>
<div className='friendsSection'>
<h2>Friends</h2>
<input onChange=(e) => setFriendFilter(e.target.value) type='text' placeholder='Enter a username'/>
<div className='friendsListContainer'>
allFriends.length
?
<div className='friendsList'>
//-----------------------------------------------------------------------------------
// Map through the user's friends
// Return a single friend div w/ their username and status
//-----------------------------------------------------------------------------------
allFriends.map(f =>
if (f.name.toLowerCase().includes(friendFilter.toLowerCase()))
return <SingleFriend key=f.name name=f.name status=f.status/>
else return null
)
</div>
: <h4 className='noFriends'>No friends have been added</h4>
</div>
<div className='addFriend'>
<h3 className='addFriendText' >Add a friend</h3>
<input className='addFriendInput' onChange=(e) => setFriendSearch(e.target.value) type='text' placeholder='Enter a username'/>
<button onClick=addFriend >Add</button>
</div>
</div>
</div>
)
export default Friends;
【问题讨论】:
嗨!请使用tour(您将获得徽章!),环顾四周,并阅读help center,尤其是How do I ask a good question?,我还推荐Jon Skeet 的Writing the Perfect Question。请将问题中的代码减少为minimal reproducible example,最好是使用堆栈片段([<>]
工具栏按钮)可运行的代码。 Stack Snippets 支持 React,包括 JSX; here's how to do one.
首先,setUnsortedFriends(allF);
将永远是setUnsortedFriends([]);
,因为您有一个 fetch() 的 for 循环,并且在您调用 setUnsortedFriends()
之后它们都会完成很长时间。您需要使用 Promise.all() 或 async / await。
核心问题的主要参考:***.com/questions/23667086/…
【参考方案1】:
你需要等待获取响应数据
const fetchFriendData = async (allFriendNames) =>
let allF = [];
for (let friend of allFriendNames)
const response = await fetch(`http://localhost:8000/findFriend?username=$friend`)
const user = await response.json()
if (user.socketid)
allF.push(name: user.username, status: 'online')
else
allF.push(name: user.username, status: 'offline')
document.querySelector('.addFriendInput').value = '';
setUnsortedFriends(allF);
【讨论】:
以上是关于即使在状态更改后组件也不会更新的主要内容,如果未能解决你的问题,请参考以下文章