如何使用useEffect设置状态并避免无限重渲染(医生评分场景)
解决无限重渲染并实现需求的方案
1. 修复useEffect的依赖与执行逻辑
无限重渲染的核心原因是useEffect依赖了doctor状态:初始doctor为null时触发请求,请求完成后setDoctor(data)更新状态,组件重渲染,useEffect因doctor引用变化再次执行;后续用户评分后setDoctor(null),又会循环触发请求→更新状态→重渲染的流程,形成无限循环。
将useEffect的依赖改为医生id,并调整加载逻辑,确保页面刷新或医生ID变化时自动获取数据:
useEffect(() => { axios.get(`doctor/${id}`).then(({data}) => { setDoctor(data) }) }, [id])
2. 优化评分后的医生数据更新逻辑
无需通过setDoctor(null)触发重新加载,直接在评分请求成功后获取最新的医生数据,确保平均评分实时更新:
const handleReview = async () => { try { if(text === '' || rating === 0){ errorNotification('field cannot be empty') }else { await axios.post(`/doctor/${id}/review`, { text, rating, createdAt: moment(dayjs(date).toDate()).format('LL') }) // 评分成功后重新获取最新的医生数据,更新状态 const {data} = await axios.get(`doctor/${id}`) setDoctor(data) setText('') setRating(0) setGiveReview(false) successfulNotification('feedback received') } } catch (error) { errorNotification('error, please try again later') } }
如果后端在评分接口返回更新后的医生信息,也可以直接用返回值更新doctor状态,省去一次GET请求:
// 替换上面的GET请求逻辑 const response = await axios.post(`/doctor/${id}/review`, {/* 请求参数 */}) setDoctor(response.data.updatedDoctor)
3. 可选优化:防止重复请求
若存在医生ID频繁变化的场景,可添加加载状态避免重复请求:
const [isLoading, setIsLoading] = useState(false) useEffect(() => { const fetchDoctor = async () => { if(isLoading) return setIsLoading(true) try { const {data} = await axios.get(`doctor/${id}`) setDoctor(data) } finally { setIsLoading(false) } } fetchDoctor() }, [id])
内容的提问来源于stack exchange,提问作者gerard
相关产品推荐
相关产品推荐

