React中useEffect内setState后如何立即取值且避免无限循环?
问题根因
- 首先代码存在笔误:声明状态应该使用
useState而非setState,先修正这处问题。 - setState是异步批量更新的,调用
setUsersInfo后,当前作用域下的usersInfo还是本次渲染对应的旧值,所以立刻打印拿不到最新数据。 - 把
usersInfo加入依赖后触发无限循环的原因:useEffect依赖变化就会重新执行,而你每次执行useEffect都会调用setUsersInfo修改usersInfo的值,进而触发重渲染、再次执行useEffect,形成死循环。
解决方案
根据你的使用场景选择对应方案即可:
方案1:接口返回数据后直接处理筛选
如果你只是需要用本次接口返回的数据做筛选,不需要等状态更新后再处理,直接在拿到接口返回值的位置写筛选逻辑即可,不需要把usersInfo加到请求接口的useEffect依赖中:
import { useState, useEffect } from 'react' // 修正笔误,使用useState声明状态 const[usersInfo, setUsersInfo] = useState('') useEffect(()=>{ async function fetchUsers(){ const response = await fetch(`http://localhost:8083/api/patient/findAll`); const json = await response.json(); setUsersInfo(json) // 直接在这里处理筛选、打印等逻辑,拿到的就是最新数据 console.log('最新用户数据', json) const filteredData = json.filter(item => /* 你的筛选条件 */) // 如果需要存储筛选结果可以声明对应state存储 } fetchUsers() },[])
方案2:单独用useEffect监听状态变化处理筛选
如果你需要基于更新后的usersInfo状态做响应式处理(比如后续还有其他操作会修改usersInfo,筛选逻辑需要跟着状态变化自动执行),把请求逻辑和筛选逻辑拆分成两个独立的useEffect即可:
import { useState, useEffect } from 'react' const[usersInfo, setUsersInfo] = useState('') const [filteredUsers, setFilteredUsers] = useState([]) // 仅负责首次请求数据,无多余依赖不会重复执行 useEffect(()=>{ async function fetchUsers(){ const response = await fetch(`http://localhost:8083/api/patient/findAll`); const json = await response.json(); setUsersInfo(json) } fetchUsers() },[]) // 专门监听usersInfo变化处理筛选逻辑 useEffect(() => { // 初始值为空时跳过逻辑 if (!usersInfo) return const filteredData = usersInfo.filter(item => /* 你的筛选条件 */) setFilteredUsers(filteredData) console.log('更新后的用户数据', usersInfo) }, [usersInfo])
方案3:无副作用的筛选逻辑用useMemo优化
如果你的筛选逻辑没有副作用(不需要打印、不需要调用其他接口等操作),直接用useMemo计算筛选结果即可,不需要额外声明state和useEffect,性能更好:
import { useState, useEffect, useMemo } from 'react' const[usersInfo, setUsersInfo] = useState('') // 仅当usersInfo变化时才会重新计算筛选结果 const filteredUsers = useMemo(() => { if (!usersInfo) return [] return usersInfo.filter(item => /* 你的筛选条件 */) }, [usersInfo]) useEffect(()=>{ async function fetchUsers(){ const response = await fetch(`http://localhost:8083/api/patient/findAll`); const json = await response.json(); setUsersInfo(json) } fetchUsers() },[])
内容的提问来源于stack exchange,提问作者Ragu
相关产品推荐
相关产品推荐

