React中状态变化时useSWR未重新获取数据问题排查
问题分析与修复方案
核心问题1:初始化选中用户未同步异步数据
你用useState(allUsers?.[0])初始化选中用户,但allUsers是通过useSWR异步获取的——组件第一次渲染时allUsers是undefined,所以userSelected初始值为undefined。而且useState的初始值仅在组件首次渲染时生效,当allUsers加载完成后,userSelected不会自动更新为数组第一个用户。
核心问题2:SWR请求未绑定选中用户标识
获取单个用户数据的useSWR使用固定key /api/getUserByUserId,SWR会依据这个key缓存请求结果。切换选中用户时,key未发生变化,SWR判定无需重新请求,因此不会更新数据。另外,fetchUserByUserId依赖外部的userSelected,但该依赖未被SWR监控,进一步导致请求不会触发更新。
修复步骤
1. 同步初始选中用户与异步加载的allUsers
用useEffect监听allUsers的变化,当allUsers加载完成且未选中任何用户时,自动设置第一个用户为选中项:
useEffect(() => { if (allUsers && !userSelected) { setUserSelected(allUsers[0]); } }, [allUsers, userSelected]);
2. 给SWR添加动态key,绑定选中用户ID
将userSelected?.userId加入SWR的key中,这样选中用户变化时key会改变,SWR会自动重新发起请求。同时调整fetcher函数,避免依赖外部状态,改为通过参数接收userId:
// 调整fetcher,通过参数接收userId const fetchUserByUserId = async (url, userId) => await fetch(url, { method: "PUT", body: JSON.stringify({ userId }), headers: { "Content-Type": "application/json", }, }).then((res) => res.json()); // 使用包含userId的数组作为SWR的key,无选中用户时暂停请求 const { data: userById, error: userByIdError } = useSWR( userSelected ? ["/api/getUserByUserId", userSelected.userId] : null, ([url, userId]) => fetchUserByUserId(url, userId) );
3. 清理无效代码
原代码中useEffect调用的fetchHoursByUserId未定义,若该请求也需管理,建议同样用SWR+动态key的方式处理;若无需保留,直接删除该useEffect即可。
修复后核心代码片段
export default function ManageUsers() { const fetcher = (url) => fetch(url).then((res) => res.json()); const { data: allUsers, error: allUsersError } = useSWR( "/api/getUsers", fetcher ); const [userSelected, setUserSelected] = useState(null); // 同步初始选中用户 useEffect(() => { if (allUsers && !userSelected) { setUserSelected(allUsers[0]); } }, [allUsers, userSelected]); const fetchUserByUserId = async (url, userId) => await fetch(url, { method: "PUT", body: JSON.stringify({ userId }), headers: { "Content-Type": "application/json", }, }).then((res) => res.json()); // 动态key触发SWR自动更新 const { data: userById, error: userByIdError } = useSWR( userSelected ? ["/api/getUserByUserId", userSelected.userId] : null, ([url, userId]) => fetchUserByUserId(url, userId) ); // 下拉选择器的 onChange 处理函数 const handleUserSelect = (selectedUser) => { setUserSelected(selectedUser); }; return (<>...</>) }
内容的提问来源于stack exchange,提问作者Mathias Riis Sorensen
相关产品推荐
相关产品推荐

