首页 > 科技 > 早读《A Complete Guide to useEffect》

早读《A Complete Guide to useEffect》



https://overreacted.io/a-complete-guide-to-useeffect/

这篇文章 Dan 将让你最终领会使用 useEffect 的一切,由于提取精髓,因此略有删减。

由于 effect 在每次渲染后都会执行一次,因此你需要在第三个参数中放置数据的依赖关系。

我们来看一个例子:

function Counter() {  const [count, setCount] = useState(0);  function handleAlertClick() {    setTimeout(() => {      alert('You clicked on: ' + count);    }, 3000);  }  return (    

You clicked {count} times

);}

当 count 点击到 3,然后启动 handlerAlertClick ,并且在3秒内将 count 点击到5,3秒后定时器 alert 的 count 值是 3,原因其实很简单,我们的函数组件渲染时每次都会被调用,而这个定时器捕获的其实是当时状态下的值。

这种状况下,我们可以更好的理解 effect 是如何获取最新 count 的值的,我们来看另外一个例子:

function Counter() {  const [count, setCount] = useState(0);  useEffect(() => {    document.title = `You clicked ${count} times`;  });  return (    

You clicked {count} times

);}

并不是 count 的值在不变的 effect 中发生了改变,而是每一次渲染中 effect 都不相同。其实 effect 函数也是属于上述类似的事件处理函数,每次渲染都是不同的 effect 函数,并且每个 effect 函数捕获的都是当时状态下的 props 和 state 值。

我们需要理解 useEffect 并不完全等同于 componentDidMount,由于闭包的原因它获取的 props 和 state 都是旧值,如果你想获取最新的,你可以使用 ref,我们需要明白的是它的建立并不是来反应生命周期,而是实现状态的同步。

effect 提供的清理机制,本质上来说只是消除副作用,比如订阅的取消。我们可以从其中理解 effect 的执行顺序,上一次的 effect 会在重新渲染后被清除。因此这个清除的动作并不会捕获到最新的 props 或 state ,它只会读取到定了它那次渲染时的状态。

effect 的好处在于可以在此处理 React 之外的东西,比如 DOM 的操作等。

一般情况下建议是把不依赖 props 和 state 的函数放到组件外部,把那些仅被 effect 使用的函数放到 effect 内部。当然如果你使用到了组件内的函数(比如 props 传递进来的函数)都可以在定义的地方使用 useCallback 包一层。

我们需要保持对依赖项的关注,因为我们在某些情况下,没必要每次都去执行一下 effect ,这很不可取。如果某些函数仅在effect中调用,你可以把它们的定义移到effect中,在依赖项中处理好函数依赖的计算的值即可。

让我们来看另外一个例子:

function Article({ id }) {  const [article, setArticle] = useState(null);  useEffect(() => {    let didCancel = false;    async function fetchData() {      const article = await API.fetchArticle(id);      if (!didCancel) {        setArticle(article);      }    }    fetchData();    return () => {      didCancel = true;    };  }, [id]);  // ...}

一般异步的情况中会存在这种竞态的问题,最简单的方式是使用一个布尔值来跟踪它。

最后结论:

Hooks太新了所以大家都还在低水平地使用它,尤其是在一些教程示例中。但在实践中,社区很可能即将开始高水平地使用Hooks,因为好的API会有更好的动量和冲劲。

本文来自投稿,不代表本人立场,如若转载,请注明出处:http://www.souzhinan.com/kj/270462.html