站长网 资讯 effect的更新依赖屈指可数

effect的更新依赖屈指可数

副标题#e# useEffect中的第二个参数,可以是一个参数数组(依赖数组)。React更新DOM的思想,不管过程怎样,只将结果展示给世人。 React在更新组件的时候,会对比props,通过AST等方式比较,然后仅需更新变化了的DOM。 第二个参数相当于告诉了useEffect,只要

副标题#e#

useEffect中的第二个参数,可以是一个参数数组(依赖数组)。React更新DOM的思想,不管过程怎样,只将结果展示给世人。

React在更新组件的时候,会对比props,通过AST等方式比较,然后仅需更新变化了的DOM。

第二个参数相当于告诉了useEffect,只要我给你的这些参数任中之一发生了改变,你就执行effect就好了。如此,便可以减少每次render之后调用effect的情况,减少了无意义的性能浪费。

那么在开发过程中,我们会尝试在组件载入时候,通过api获取远程数据,并运用于组件的数据渲染,所以我们使用了如下的一个简单例子:

useEffect(() => { 

  featchData(); 

}, []); 

由于是空数组,所以只有在组件挂载(mount)时获取一遍远程数据,之后将不再执行。如果effect中有涉及到局部变量,那么都会根据当前的状态发生改变,函数是每次都会创建(每次都是创建的新的匿名函数)。

function Counter() { 

  const [count, setCount] = useState(0); 

 

  useEffect(() => { 

    const id = setInterval(() => { 

      setCount(count + 1); 

    }, 1000); 

    return () => clearInterval(id); 

  }, []); 

 

  return <h1>{count}</h1>; 

你可能会认为上面的例子,会在组件加载后,每秒UI上count+1,但实际情况是只会执行一次。为什么呐?是不是觉得有些违反直觉了?

因为,并没有给effect的依赖项加入count,effect只会在第一次渲染时候,创建了一个匿名函数,尽管通过了setInterval包裹,每秒去执行count + 1,但是count的值始终是为0,所以在UI表现上永远渲染的是1。

当然,通过一些规则,我们可以通过加上count来改变其值,或者通过useRef,或者通过setState(x => x+1),模式来实现获取最新的值。例如下面的黑科技操作:

// useRef 

function Example() { 

  const [count, setCount] = useState(0); 

  const countRef = useRef(count); 

  countRef.current = count; // 假如这一行代码放到effect函数中会怎么样呐?可以思考下! 

  // answer: 在effect中count是effect匿名函数声明时就有了,值就是0,那么拿到的count值自然也是渲染前(本次props中的值)的count(值为0,再次复盘理解下快照的概念),但由于依赖数组中并不存在任何依赖,所以该匿名函数不会二次执行。 

  // 但,由于setInterval的原因,函数会不停地setCount,关键是其中的参数了,countRef.current = count;取到的值是第一次快照时候的值0,所以其更新的值永远为0+1 = 1。这样的结果是符合预期规则的。 

  // 那为什么放在外面就好了呐?因为countRef.current同步了count的最新值,每次render前就拿到了新的count值,并且赋值给countRef.current,由于ref的同步特性(及时性、统一性),所以循环中获取的countRef.current也是最新的值,故而能实现计数效果 

 

  useEffect(() => { 

    const id = setInterval(() => { 

      setCount(countRef.current + 1); 

    }, 1000); 

    return () => clearInterval(id); 

  }, []); 

 

  return <h1>{count}</h1>; 

 

// setState传入函数 

function Example() { 

  const [count, setCount] = useState(0); 

 

  useEffect(() => { 

    const id = setInterval(() => { 

#p#副标题#e#

      setCount(x => x + 1);  // 传递参数为一个函数时候,默认传递的第一个参数是之前的值,这是useState的hook在处理 

    }, 1000); 

    return () => clearInterval(id); 

  }, []); 

 

  return <h1>{count}</h1>; 

 

// 使用useReducer 

function Counter({ step }) { 

  const [count, dispatch] = useReducer(reducer, 0); 

 

  function reducer(state, action) { 

    if (action.type === 'tick') { 

      return state + step; 

    } else { 

      throw new Error(); 

    } 

  } 

 

  useEffect(() => { 

    const id = setInterval(() => { 

      dispatch({ type: 'tick' }); 

    }, 1000); 

    return () => clearInterval(id); 

  }, [dispatch]); 

 

  return <h1>{count}</h1>; 

本文来自网络,不代表站长网立场,转载请注明出处:https://www.zwzz.com.cn/html/biancheng/zx/2021/0523/4670.html

作者: dawei

【声明】:站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。
联系我们

联系我们

0577-28828765

在线咨询: QQ交谈

邮箱: xwei067@foxmail.com

工作时间:周一至周五,9:00-17:30,节假日休息

返回顶部