React中useEffect获取用户信息时未执行的问题求助
问题
尝试通过useEffect调用axios获取用户信息并渲染页面,但进入页面后完全空白,且出现「无法读取null的属性」错误。在请求逻辑内添加了console.log但从未输出,说明useEffect中的函数未执行。
代码如下:
function User() { const[userInfo, setUserInfo] = useState(null); const {user, checkAuth} = useContext(UserContext); const [redirect, setRedirect] = useState(false); const params = useParams(); function logout() { axios.post('http://localhost:3030/logout', {}, {withCredentials: true}) .then(() => { checkAuth().catch(() => setRedirect(true)); }); } useEffect(() => { function getUserInfo() { axios.get('http://localhost:3030/users/'+params.id) .then(response => { setUserInfo(response.data); console.log('here'); //this never shows in the console }); } getUserInfo(); }, [params.id]); if (redirect) { return (<Navigate to={'/'} />); } return ( <main> <Container> <ContainerHeader> <StyledHeader>Profile</StyledHeader> {!!userInfo && !!user && parseInt(params.id) === user.id && ( <LinksRow> <EditLinkButton to={'/profile'}><FontAwesomeIcon icon={faEdit} /> Edit</EditLinkButton> <Button onClick={() => logout()}><FontAwesomeIcon icon={faArrowRight} /> Logout</Button> </LinksRow> )} </ContainerHeader> <Img src={ProfileImg} alt=""/> <Name>{userInfo.first_name} {userInfo.last_name}</Name> <Role>{userInfo.role}</Role> <Role>{userInfo.sector}</Role> <Labels><FontAwesomeIcon icon={faEnvelope}/> {userInfo.email}</Labels> <Labels> <FontAwesomeIcon icon={faLocationDot} /> {userInfo.location} </Labels> <Labels> <Links href={userInfo.link} target="_blank"> <FontAwesomeIcon icon={faExternalLink} /> {userInfo.link}</Links> </Labels> <Labels> <FontAwesomeIcon icon={faCoins} /> 100 CxCoins</Labels> <SecondHeader>Statistics</SecondHeader> <Labels> <FontAwesomeIcon icon={faComment} /> 100 comments</Labels> <Labels> <FontAwesomeIcon icon={faTicket} /> 100 tickets</Labels> </Container> </main> ); } export default User
解决方案
核心问题分析
页面空白+useEffect未执行的根源是组件渲染阶段直接访问了null类型的userInfo属性,导致渲染报错,组件直接终止执行,useEffect根本没机会运行。
具体修复步骤
修复渲染时的null访问错误
userInfo初始值为null,直接渲染userInfo.first_name这类属性会触发报错。需要给所有依赖userInfo的内容添加条件判断,或者使用可选链操作符:- 方案一:用条件判断包裹整个用户信息区域
- 方案二:给每个属性添加可选链(
userInfo?.first_name)
给axios请求添加错误捕获
即使修复了渲染问题,请求也可能因为网络、接口错误失败,添加catch可以排查问题,避免后续逻辑中断。验证
params.id的有效性
确认路由是否正确配置了:id参数,useParams能正常获取到值,否则请求地址无效,也不会进入then回调。
修改后的代码示例
function User() { const[userInfo, setUserInfo] = useState(null); const {user, checkAuth} = useContext(UserContext); const [redirect, setRedirect] = useState(false); const params = useParams(); function logout() { axios.post('http://localhost:3030/logout', {}, {withCredentials: true}) .then(() => { checkAuth().catch(() => setRedirect(true)); }); } useEffect(() => { // 先判断params.id是否存在,避免无效请求 if (!params.id) return; function getUserInfo() { axios.get(`http://localhost:3030/users/${params.id}`) .then(response => { setUserInfo(response.data); console.log('here'); }) // 添加错误捕获,排查请求问题 .catch(err => { console.error('获取用户信息失败:', err); }); } getUserInfo(); }, [params.id]); if (redirect) { return (<Navigate to={'/'} />); } return ( <main> <Container> <ContainerHeader> <StyledHeader>Profile</StyledHeader> {!!userInfo && !!user && parseInt(params.id) === user.id && ( <LinksRow> <EditLinkButton to={'/profile'}><FontAwesomeIcon icon={faEdit} /> Edit</EditLinkButton> <Button onClick={() => logout()}><FontAwesomeIcon icon={faArrowRight} /> Logout</Button> </LinksRow> )} </ContainerHeader> <Img src={ProfileImg} alt=""/> {/* 用条件判断包裹所有依赖userInfo的内容 */} {userInfo && ( <> <Name>{userInfo.first_name} {userInfo.last_name}</Name> <Role>{userInfo.role}</Role> <Role>{userInfo.sector}</Role> <Labels><FontAwesomeIcon icon={faEnvelope}/> {userInfo.email}</Labels> <Labels> <FontAwesomeIcon icon={faLocationDot} /> {userInfo.location} </Labels> <Labels> <Links href={userInfo.link} target="_blank"> <FontAwesomeIcon icon={faExternalLink} /> {userInfo.link}</Links> </Labels> </> )} <Labels> <FontAwesomeIcon icon={faCoins} /> 100 CxCoins</Labels> <SecondHeader>Statistics</SecondHeader> <Labels> <FontAwesomeIcon icon={faComment} /> 100 comments</Labels> <Labels> <FontAwesomeIcon icon={faTicket} /> 100 tickets</Labels> </Container> </main> ); } export default User
内容的提问来源于stack exchange,提问作者justanothernoob
相关产品推荐
相关产品推荐

