关于useEffect依赖dispatch的工作原理及相关疑问
React-Redux与useEffect常见疑问解答
针对你提供的测验集获取组件,以下是四个疑问的具体解答:
1. 直接调用dispatch(FetchQuestions)会触发无限循环,为何useEffect后仅执行一次?
如果直接在组件函数体里写dispatch(FetchQuestions("self_created")),组件每次渲染时都会执行这条代码。dispatch会触发Redux状态更新,状态更新又会导致组件重新渲染,形成「渲染→dispatch→状态更新→渲染」的无限闭环。
而useEffect的执行时机由依赖数组控制:当依赖数组是[dispatch]时,由于dispatch是Redux提供的稳定引用(组件生命周期内不会变化),所以useEffect只会在组件挂载时执行一次,后续除非依赖项改变才会重新触发,从根源上避免了循环。
2. 为何useEffect依赖dispatch时,内部调用dispatch仍能正常工作?
useDispatch返回的dispatch函数是一个稳定不变的引用——不管组件渲染多少次,这个函数的地址都不会变。把它放进useEffect的依赖数组里,不会导致useEffect反复触发。
同时,React要求useEffect内部用到的外部变量必须声明在依赖数组中,这里声明dispatch作为依赖,既符合React的规则,又不会引发额外的执行,所以内部调用dispatch完全正常。
3. dispatch触发FetchQuestions后,question_set_self_created的值是如何更新的?
完整的更新流程如下:
- 调用
dispatch(FetchQuestions("self_created"))时,FetchQuestions应该是一个异步action(通常用Redux-Thunk中间件实现),它会向MongoDB发起数据请求; - 请求成功拿到测验数据后,这个异步action会再dispatch一个同步action(比如类型为
FETCH_SELF_CREATED_SUCCESS的action),并把获取到的测验数据作为payload传入; - 对应的Redux reducer会监听这个同步action,根据payload更新
state.user.question_set_self_created的值; useSelector会实时监听Redux状态变化,当question_set_self_created更新后,组件会自动重新渲染,拿到最新的状态值。
4. 状态更新后组件重新渲染,为何未出现延迟问题?
主要有两个原因:
- React的虚拟DOM Diff算法会只更新页面中实际变化的部分,不会全量重绘,渲染开销极小,用户几乎感知不到;
- 初始状态下
question_set_self_created应该是一个空数组或默认值,组件第一次渲染时会先展示这个默认状态;如果你的MongoDB请求速度较快,状态更新的间隔很短,用户就不会察觉到延迟。如果后续遇到请求慢的情况,可以添加loading状态提示用户。
内容的提问来源于stack exchange,提问作者Tanishk Goyal
相关产品推荐
相关产品推荐

