什么是副作用
- 直接将修改 state 的逻辑写到组件中,导致组件不断的循环渲染,直至调用次数过多导致内存溢出
React.StrictMode
- 在React严格模式下,会重新执行两次组件函数,以帮我们把副作用显示出来,在开发环境中以手动解决它
- 在生产环境下不生效,在开发环境中才生效
setState 的执行流程
- 底层是调用
dispatchSetDate()
函数,渲染阶段不检查值,非渲染阶段检查值 -
- 如果是渲染阶段(比如直接把 setState 写在组件函数中,setState 直接执行),无论值是否改变都会重新渲染
-
- 如果是非渲染阶段(比如把 setState 写在按钮点击的回调中)
- 如果值不同,对组件重新渲染
- 如果值相同,不会对组件重新渲染。但是在一些特殊情况,比如刚刚重复的第一次也会重新渲染,但只是当前组件重新渲染,其他组件不发生
- 如果是非渲染阶段(比如把 setState 写在按钮点击的回调中)
使用 setTimeout 解决渲染阶段 setState 重复执行
使用 useEffect 解决渲染阶段 setState 重复执行
- useEffect 接收的第一个参数是回调函数
- useEffect 接收的第二个参数是数组,表示它的依赖项,当他的依赖项发生改变时才会执行回调(通常会把回调中使用到的变量都设置为依赖)
- 如果不传第二参数,那么每次组件每次渲染完后都会执行回调
- 如果第二参数为空数组,那么只在初次渲染完成后调用,适合初始化请求数据
- useEffect 的清理函数:在回调中返回一个函数,这个函数会在下次 Effect 调用前执行,清理上次的影响
–> 两种方法的原理都是把 setState 放到渲染函数执行后(非渲染阶段)
useReducer 整合器(抽象整合 useState)
参数:
- 回调(reducer整合函数):
- 接收第一个参数为 state 最新值,第二个参数为 stateDispatch 传递的值(action 的 type 类型)
- 返回值成为 state 的新值
- 初始值
由于 reducer整合函数一般创建后不会改变,所以尽量写在组件函数外部,减少函数重新渲染时重新创建
返回值:
- state 值
- 修改 state 的派发器:stateDispatch 函数,当你要修改 state 时,调用这个方法,并传入 type 标识要触发的更新方法
React.memo
接收一个组件作为参数,返回一个包装过的新组件
作用:这个新的组件在父组件中使用,当父组件重新渲染时,经过 memo
包装的子组件会检查 props 是否变化,不变化的话直接使用缓存中的值不重新渲染,props 改变时才重新渲染。
useCallback
参数:(回调函数,依赖数组)
返回值:新的回调函数
作用:这个回调函数不会在组件重新渲染时重新创建,导致子组件感知到 props 变化而重新渲染。而是当依赖数组发生变化时才重新创建回调函数