React中含Axios的useEffect多次触发问题及解决方法
解决React useEffect无限循环问题
我正在学习React JS,遇到一个问题:即使在useEffect的依赖项中传入了state值userList,useEffect仍会被多次触发,甚至陷入无限循环,控制台不断输出"I am inside useEffect"。以下是我的代码:
import axios from 'axios'; import React, { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom'; const ViewProfileUseEffect = () => { const [userList, setUserList] = useState([]); const naviagte = useNavigate(); useEffect(() => { axios.get("http://localhost:4000/users").then((response) => { setUserList(response.data); console.log('I am inside useEffect'); }).catch((error) => { alert("Something went wrong") }) }, [userList]); function handleProfile(id) { naviagte(`/profile/${id}`); } function deleteProfile(id) { axios.delete(`http://localhost:4000/users/${id}`).then((response) => { console.log(`Delete Response Data ${response.data}`); }).catch((error) => { alert("Something went Wrong"); }) } return ( <> <h3>View Profile</h3> <div className='container' style={{ backgroundColor: 'bisque', width: '500px', padding: '20px', borderRadius: '5px' }}> <table className='table'> <thead> <tr> <th scope='col'>UserName</th> <th scope='col'>Email ID</th> <th scope='col'>Action</th> </tr> </thead> <tbody> {userList.map((user) => { return ( <tr key={user.id}> <td>{user.userName}</td> <td>{user.userEmail}</td> <td> <button className="btn btn-warning" onClick={() => handleProfile(user.id)}>View Profile</button> <button className="btn btn-danger" onClick={() => deleteProfile(user.id)}>Delete Profile</button> </td> </tr> ) })} </tbody> </table> </div> </> ) } export default ViewProfileUseEffect
问题根源
你将userList加入了useEffect的依赖数组,但在useEffect内部又通过setUserList(response.data)更新这个state。每次userList被更新,组件会重新渲染,依赖数组的变化会再次触发useEffect,最终形成无限循环。
修复方案
1. 移除不必要的依赖(核心修复)
这个useEffect的作用是初始化加载用户列表,只需要在组件挂载时执行一次,因此依赖数组应设为空数组[],确保useEffect仅在组件首次渲染时运行:
useEffect(() => { axios.get("http://localhost:4000/users").then((response) => { setUserList(response.data); console.log('I am inside useEffect'); }).catch((error) => { alert("Something went wrong") }) }, []); // 空依赖数组,仅组件挂载时执行
2. 优化删除操作后的列表更新(体验优化)
当前删除用户后页面不会自动刷新列表,你可以在deleteProfile的成功回调中直接更新本地state,避免重新请求整个列表:
function deleteProfile(id) { axios.delete(`http://localhost:4000/users/${id}`).then((response) => { console.log(`Delete Response Data ${response.data}`); // 基于前一个state过滤掉被删除的用户 setUserList(prevList => prevList.filter(user => user.id !== id)); }).catch((error) => { alert("Something went Wrong"); }) }
小提示
注意到你代码里的naviagte是拼写错误,正确应为navigate,虽然不影响当前问题,但修正后可避免后续路由跳转的潜在错误。
内容的提问来源于stack exchange,提问作者Viknesh k m
相关产品推荐
相关产品推荐

