每次渲染都有它自己的Effects
count
是某个特定渲染中的常量。事件处理函数“看到”的是属于它那次特定渲染中的count
状态值。对于effects也同样如此:
并不是count
的值在“不变”的effect中发生了改变,而是effect 函数本身在每一次渲染中都不相同,概念上它是组件输出的一部分,可以看到属于某次特定渲染的props和state
Effects的清除
effects有时候需要有一个清理步骤,目的是消除副作用,React只会在浏览器绘制后运行effects,这使得你的应用更流畅,因为大多数effects不会阻塞屏幕的更新,effects的清除同样被延迟,上一次的effect会在重新渲染后被清除
- React 渲染
{id: 20}
的UI。 - 浏览器绘制。我们在屏幕上看到
{id: 20}
的UI。 - React 清除
{id: 10}
的effect。 - React 运行
{id: 20}
的effect。
effect的清除不会读取最新的props,它只能读取到定义它的那次渲染中华的prop值
告诉React去比对你的Effects
这是为什么你如果想要避免effects不必要的重复调用,你可以提供给useEffect
一个依赖数组参数(deps):
1 | useEffect(() => { |
这好比你告诉React:“Hey,我知道你看不到这个函数里的东西,但我可以保证只使用了渲染中的name
,别无其他。”
移除依赖
1 | useEffect(() => { |
定时器会在每一次count
改变后清除和重新设定
1 | useEffect(() => { |
React已经知道当前的count,我们需要告知React的仅仅是去递增状态,不管它现在具体是什么值
解耦来自Actions的更新
当你写setSomething(something=>…)这种代码时可以考虑使用reducer,reducer可以让你把组件内发生了什么和状态如何响应并更新分开描述
我们用一个dispatch依赖去替换effect的step依赖
1 | const [state, dispatch] = useReducer(reducer, initialState); |
1 | const initialState = { |
React保证dispatch在每次渲染中都是一样的,所以可以在依赖中去掉它,不会引起effect不必要的重复执行,当dispatch时,React只记住了action,它会在下一次渲染中再次调用reducer
无限重复请求问题:
1 没有依赖数组,那么每次渲染都会触发这个副作用
1 | useEffect(()=>{ |
2 设置了依赖数组,但是依赖数组里的变量一直在变
1 | const [data,setData] = useState() |
定义函数请求
某些函数只在effect中使用,那就在effect中定义
某些函数在多个地方使用,就独立定义,最好用useCallBack包裹,并且在依赖数组里把依赖项写全
eg:
1 | function SearchResults() { |
如果query不变,getFetchUrl也会保持不变,effect也不会重新运行,反之,query改变了,getFetchUrl也会随之改变
参考: