React Redux中useState获取用户状态报错,该选择哪种方式?
首先咱们先搞清楚为什么用useState的方式会报错:
你初始化user状态的时候没给初始值,所以组件第一次渲染时user是undefined。这时候你直接访问user.roleId,自然会抛出Cannot read properties of undefined (reading 'roleId')的错误。虽然你在useEffect里订阅了Redux状态更新并设置user,但useEffect是组件挂载后才执行的,第一次渲染的时候还没走到这一步,所以初始渲染时user还是空的。
接下来对比你提到的两种方式,再说说更优的方案:
1. 直接使用authStore.getState()的方式
这种方式确实能正常工作,优点是简单直接,不需要额外维护组件内部状态,每次组件渲染都会拿到最新的Redux状态。不过要注意一个点:如果你的组件在登录前就渲染(也就是Redux里还没有user数据),直接访问authStore.getState().user.roleId还是会报错,这时候最好加上可选链或者空值判断,比如写成authStore.getState().user?.roleId === 2,或者先判断user是否存在:
{authStore.getState().user && authStore.getState().user.roleId === 2 && <>Followers: {props.vacation.followersCount}</>}
这种方式适合简单场景,但如果组件频繁渲染,每次都调用getState其实性能影响不大(Redux的getState是轻量操作),但代码会有点冗余。
2. 修复useState + useEffect的方式(如果想保留这种写法)
如果你坚持要用组件内部状态缓存Redux的用户数据,可以通过以下两种方式修复报错:
- 给useState设置初始值:直接从Redux获取初始状态,避免第一次渲染时
user是undefined:const [user, setUser] = useState<UserModel | undefined>(authStore.getState().user); - 添加空值判断:在访问
roleId前先确认user存在,或者用可选链操作符:{user?.roleId === 2 && <>Followers: {props.vacation.followersCount}</>} // 或者 {user && user.roleId === 2 && <>Followers: {props.vacation.followersCount}</>}
不过这种方式需要手动维护订阅,代码相对繁琐,不如官方推荐的方式简洁。
更推荐的最佳实践:使用Redux官方的useSelector钩子
其实你现在的两种方式都不是最优解,Redux官方专门为React提供了react-redux库,其中的useSelector钩子是获取Redux状态的标准方式。它会自动订阅状态变化,当Redux里的user更新时,组件会自动重新渲染,代码也更简洁:
import { useSelector } from 'react-redux'; // 导入你的store类型,确保类型正确 import { AuthState } from '../../../Redux/AuthState'; function VacationCard(props: VacationCardProps): JSX.Element { // 直接从Redux状态中获取user,类型会自动推导 const user = useSelector((state: AuthState) => state.user); return ( <div className="VacationCard"> {/* 其他内容 */} {user?.roleId === 2 && <>Followers: {props.vacation.followersCount}</>} {/* 其他内容 */} </div> ); }
这种方式既不需要手动写useEffect订阅,也不会有初始状态的问题(只要加上可选链判断),完全符合Redux的最佳实践,代码也更干净。
总结选择建议
- 如果你的项目已经引入了
react-redux,优先用useSelector,这是最标准的做法; - 如果不想用
react-redux,可以选择直接调用authStore.getState(),记得加上空值判断; useState + useEffect的方式可以用,但代码冗余,不推荐作为长期方案。
内容的提问来源于stack exchange,提问作者DennisR93

