reactjs - useEffect 陷入无限循环
问题描述
我得到一个无限循环,我知道问题是因为我在 useEffect 函数中将“posts”和“setPost”作为第二个参数放在括号中,但是每当我添加新帖子时,我都需要渲染页面,所以帖子必须放在括号中。
function Home() {
const {userData, setUserData} = useContext(userContext)
const [posts, setPost] = useState([])
const [createPost, setCreatePost] = useState('')
const handleToken = () => {
localStorage.removeItem('auth-token')
}
const token = localStorage.getItem("auth-token");
const handleOnSubmit = (e) => {
e.preventDefault()
axios.post('http://localhost:5000/posts', {textOfThePost: createPost}, {
headers: { 'auth-token': token },
})
.then((res) => {setCreatePost("")})
}
useEffect(() => {
axios.get('http://localhost:5000/posts')
.then(res => {
setPost(res.data)
})
}, [posts])
return (
<div className="home">
<div style={{display: 'flex', alignItems: 'center'}}>
<h1>this is the home: Welcome, {userData.username}</h1>
<Link style={{margin: 10}} to="/home">home</Link>
<Link style={{margin: 10}} to="/profile">profile</Link>
<Link style={{margin: 10}} onClick={handleToken} to="/">log out</Link>
</div>
<form onSubmit={handleOnSubmit}>
<input type="text" placeholder="What's happening?" value={createPost} onChange={e => setCreatePost(e.target.value)}/>
<button type="submit">tweet</button>
</form>
<div style={{display: 'flex', flexDirection: 'column'}}>
{posts.map(post => (
<div style={{border: '2px solid black', marginBottom: 10, marginRight: 'auto', marginLeft: 'auto', width: 300}} key={post._id}>
<div style={{display: 'flex', alignItems: 'center'}}>
<Avatar src={post.avatar}/>
<span style={{color: 'blue', marginLeft: 10}}>{post.name} <span style={{color: 'grey', fontSize: 11}}>@{post?.username}</span></span><br/>
</div>
<span>{post.textOfThePost}</span><br/>
<span>{moment(post.date).format('lll')}</span>
</div>
)).reverse()}
</div>
</div>
)
}
解决方案
这里的问题是(和类似的钩子)的依赖数组useEffect
不使用深度比较(出于性能原因)。
也就是说,每当您通过 Axios 获取新数据时,res.data
它是一个新的 JavaScript 对象,并且当您将其分配给状态时,效果依赖项将其视为完全更改的对象并再次运行效果,等等。
最简单的解决方法是使用深度比较useEffect
,例如https://github.com/kentcdodds/use-deep-compare-effect。