React父组件API获取数据更新后子组件未重渲染白屏问题
问题原因
- 白屏崩溃:首次渲染时父组件传入的
user初始值是空对象{},本身不存在includes数组方法,直接调用user.includes()会抛出类型错误;同时你写的user.includes(user?.id)逻辑本身有误,includes只能在数组实例上调用,普通对象调用该方法必然报错。 - 子组件不更新:
useState的初始化逻辑仅在组件首次挂载时执行1次,后续父组件props更新传入新的user值时,子组件内部的followed状态不会自动同步。你写的useEffect虽然依赖了user,但内部没有任何状态更新逻辑,自然不会触发视图重渲染。 - 额外语法问题:父组件中渲染子组件时使用了小写标签
<child />,React会将小写开头的标签识别为原生DOM节点,不会渲染你导入的Rightbar组件,也会导致异常。
修复步骤
1. 修正父组件逻辑
将user初始值设为null区分加载状态,接口返回数据前不渲染子组件,避免传入无效初始值;同时修正子组件标签名为大写开头的正确组件名。
export default function Profile() { // 初始值设为null,标记未加载状态 const [user, setUser] = useState(null); const PF = process.env.REACT_APP_PUBLIC_FOLDER; const username = useParams().username; useEffect(() => { const fetchUser = async () => { try { const res = await axios.get( `http://localhost:8000/api/users?username=` + username ); setUser(res.data); } catch (e) { console.log(e); } }; fetchUser(); }, [username]); // 数据加载中展示占位内容,不渲染子组件 if (!user) return <div>加载中</div> return <> {/* 自定义组件必须大写开头 */} <Rightbar user={user} /> </> }
2. 修正子组件逻辑
首先明确业务逻辑:includes只能用于判断某个值是否存在于数组中,你需要找到实际存储关注ID列表的数组字段(通常是当前登录用户的followings数组)再做判断,不要直接在user对象上调用该方法。
两种可选修复方案:
方案1:保留本地状态,监听props同步更新
适合需要在子组件内部修改followed状态的场景(比如点击关注/取关按钮后直接更新状态)
export default function Rightbar({ user, currentUser }) { // 初始化时做好类型校验,避免非法值报错 const [followed, setFollowed] = useState(() => { if (!user?.id || !Array.isArray(currentUser?.followings)) return false; return currentUser.followings.includes(user.id); }); // 监听依赖项变化,同步更新状态 useEffect(() => { if (!user?.id || !Array.isArray(currentUser?.followings)) { setFollowed(false); return; } setFollowed(currentUser.followings.includes(user.id)); }, [user, currentUser]); return ( // 组件业务代码 ) }
方案2:直接使用派生值,省去同步逻辑
如果followed不需要在子组件内部独立修改,完全由props计算得到,推荐用这种写法,避免状态不同步的bug
export default function Rightbar({ user, currentUser }) { // 直接根据props计算结果,props变化时自动更新 const followed = !!( user?.id && Array.isArray(currentUser?.followings) && currentUser.followings.includes(user.id) ); return ( // 组件业务代码 ) }
注意:上述代码中的
currentUser为当前登录用户对象,你需要替换为项目中实际存储登录用户信息的变量。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

