React useEffect in depth

useEffect

  1. class DogInfo extends React.Component {
  2. controller = null
  3. state = {dog: null}
  4. // we'll ignore error/loading states for brevity
  5. fetchDog() {
  6. this.controller?.abort()
  7. this.controller = new AbortController()
  8. getDog(this.props.dogId, {signal: this.controller.signal}).then(
  9. (dog) => {
  10. this.setState({dog})
  11. },
  12. (error) => {
  13. // handle the error
  14. },
  15. )
  16. }
  17. componentDidMount() {
  18. this.fetchDog()
  19. }
  20. componentDidUpdate(prevProps) {
  21. // handle the dogId change
  22. if (prevProps.dogId !== this.props.dogId) {
  23. this.fetchDog()
  24. }
  25. }
  26. componentWillUnmount() {
  27. // cancel the request on unmount
  28. this.controller?.abort()
  29. }
  30. render() {
  31. return <div>{/* render dog's info */}</div>
  32. }
  33. }
  1. function DogInfo({dogId}) {
  2. const controllerRef = React.useRef(null)
  3. const [dog, setDog] = React.useState(null)
  4. function fetchDog() {
  5. controllerRef.current?.abort()
  6. controllerRef.current = new AbortController()
  7. getDog(dogId, {signal: controllerRef.current.signal}).then(
  8. (d) => setDog(d),
  9. (error) => {
  10. // handle the error
  11. },
  12. )
  13. }
  14. // didMount
  15. React.useEffect(() => {
  16. fetchDog()
  17. // eslint-disable-next-line react-hooks/exhaustive-deps
  18. }, [])
  19. // didUpdate
  20. const previousDogId = usePrevious(dogId)
  21. useUpdate(() => {
  22. if (previousDogId !== dogId) {
  23. fetchDog()
  24. }
  25. })
  26. // willUnmount
  27. React.useEffect(() => {
  28. return () => {
  29. controllerRef.current?.abort()
  30. }
  31. }, [])
  32. return <div>{/* render dog's info */}</div>
  33. }
  34. function usePrevious(value) {
  35. const ref = useRef()
  36. useEffect(() => {
  37. ref.current = value
  38. }, [value])
  39. return ref.current
  40. }
  1. function DogInfo({dogId}) {
  2. const [dog, setDog] = React.useState(null)
  3. React.useEffect(() => {
  4. const controller = new AbortController()
  5. getDog(dogId, {signal: controller.signal}).then(
  6. (d) => setDog(d),
  7. (error) => {
  8. // handle the error
  9. },
  10. )
  11. return () => controller.abort()
  12. }, [dogId])
  13. return <div>{/* render dog's info */}</div>
  14. }

The question is not "when does this effect run" the question is "with which state does this effect synchronize with"

useEffect(fn) // all state

useEffect(fn, []) // no state

useEffect(fn, [these, states])

  1. class ChatFeed extends React.Component {
  2. componentDidMount() {
  3. this.subscribeToFeed()
  4. this.setDocumentTitle()
  5. this.subscribeToOnlineStatus()
  6. this.subscribeToGeoLocation()
  7. }
  8. componentWillUnmount() {
  9. this.unsubscribeFromFeed()
  10. this.restoreDocumentTitle()
  11. this.unsubscribeFromOnlineStatus()
  12. this.unsubscribeFromGeoLocation()
  13. }
  14. componentDidUpdate(prevProps, prevState) {
  15. // ... compare props and re-subscribe etc.
  16. }
  17. render() {
  18. return <div>{/* chat app UI */}</div>
  19. }
  20. }
  1. function ChatFeed() {
  2. React.useEffect(() => {
  3. // subscribe to feed
  4. // set document title
  5. // subscribe to online status
  6. // subscribe to geo location
  7. return () => {
  8. // unsubscribe from feed
  9. // restore document title
  10. // unsubscribe from online status
  11. // unsubscribe from geo location
  12. }
  13. })
  14. return <div>{/* chat app UI */}</div>
  15. }
  1. function ChatFeed() {
  2. React.useEffect(() => {
  3. // subscribe to feed
  4. return () => {
  5. // unsubscribe from feed
  6. }
  7. })
  8. React.useEffect(() => {
  9. // set document title
  10. return () => {
  11. // restore document title
  12. }
  13. })
  14. React.useEffect(() => {
  15. // subscribe to online status
  16. return () => {
  17. // unsubscribe from online status
  18. }
  19. })
  20. React.useEffect(() => {
  21. // subscribe to geo location
  22. return () => {
  23. // unsubscribe from geo location
  24. }
  25. })
  26. return <div>{/* chat app UI */}</div>
  27. }
  1. function ChatFeed() {
  2. // NOTE: this is pseudo-code,
  3. // you'd likely need to pass values and assign return values
  4. useFeedSubscription()
  5. useDocumentTitle()
  6. useOnlineStatus()
  7. useGeoLocation()
  8. return <div>{/* chat app UI */}</div>
  9. }
  1. // before. Don't do this!
  2. function DogInfo({dogId}) {
  3. const [dog, setDog] = React.useState(null)
  4. const controllerRef = React.useRef(null)
  5. const fetchDog = React.useCallback((dogId) => {
  6. controllerRef.current?.abort()
  7. controllerRef.current = new AbortController()
  8. return getDog(dogId, {signal: controller.signal}).then(
  9. (d) => setDog(d),
  10. (error) => {
  11. // handle the error
  12. },
  13. )
  14. }, [])
  15. React.useEffect(() => {
  16. fetchDog(dogId)
  17. return () => controller.current?.abort()
  18. }, [dogId, fetchDog])
  19. return <div>{/* render dog's info */}</div>
  20. }
  1. function DogInfo({dogId}) {
  2. const [dog, setDog] = React.useState(null)
  3. React.useEffect(() => {
  4. const controller = new AbortController()
  5. getDog(dogId, {signal: controller.signal}).then(
  6. (d) => setDog(d),
  7. (error) => {
  8. // handle the error
  9. },
  10. )
  11. return () => controller.abort()
  12. }, [dogId])
  13. return <div>{/* render dog's info */}</div>
  14. }

Conclusion

When Dan Abramov introduced hooks like useEffect, he compared React components to atoms and hooks to electrons.

They're a pretty low-level primitive, and that's what makes them so powerful.

The beauty of this primitive is that nicer abstractions can be built on top of these hooks which is frankly something we struggled with before hooks.

Since the release of hooks, we've seen an explosion of innovation and progress of good ideas and libraries built on top of this primitive which ultimately helps us develop better apps.

当丹·阿布拉莫夫(Dan Abramov)引入类似于useEffect的钩子时,他将React组件与原子相比较,并将钩子与电子相比较。

它们是一个非常低级的基元,这就是使它们如此强大的原因。

此原语的优点在于,可以在这些钩子之上构建更好的抽象,坦率地说,这是我们在使用钩子之前就遇到的难题。

自从钩子发布以来,我们已经看到了创新的飞速发展,以及在此原始基础之上构建的好主意和库,这些最终有助于我们开发更好的应用程序。

refs

https://epicreact.dev/myths-about-useeffect/



xgqfrms 2012-2020

www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!


React useEffect in depth的更多相关文章

  1. React useEffect的源码解读

    前言 对源码的解读有利于搞清楚Hooks到底做了什么,如果您觉得useEffect很"魔法",这篇文章也许对您有些帮助. 本篇博客篇幅有限,只看useEffect,力求简单明了,带 ...

  2. React Hooks in depth

    React Hooks in depth React Hooks https://reactjs.org/docs/hooks-rules.html https://www.npmjs.com/pac ...

  3. [React] Ensure all React useEffect Effects Run Synchronously in Tests with react-testing-library

    Thanks to react-testing-library our tests are free of implementation details, so when we refactor co ...

  4. React Hooks --- useState 和 useEffect

    首先要说的一点是React Hooks 都是函数,使用React Hooks,就是调用函数,只不过不同的Hooks(函数)有不同的功能而已.其次,React Hooks只能在函数组件中使用,函数组件也 ...

  5. React报错之React Hook useEffect has a missing dependency

    正文从这开始~ 总览 当useEffect钩子使用了一个我们没有包含在其依赖数组中的变量或函数时,会产生"React Hook useEffect has a missing depende ...

  6. React报错之React Hook 'useEffect' is called in function

    正文从这开始~ 总览 为了解决错误"React Hook 'useEffect' is called in function that is neither a React function ...

  7. React 中阻止事件冒泡的问题

    在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行. JS 中事件的监听与处理 事件捕获与冒泡 DOM 事件会先后经历 捕获 与 冒泡 两个阶段.捕获即事件沿着 DOM 树由上往下传递,到达 ...

  8. React hooks实践

    前言 最近要对旧的项目进行重构,统一使用全新的react技术栈.同时,我们也决定尝试使用React hooks来进行开发,但是,由于React hooks崇尚的是使用(也只能使用)function c ...

  9. 【React 资料备份】React Hook

    Hooks是React16.8一个新增项,是我们可以不用创建class组件就能使用状态和其他React特性 准备工作 升级react.react-dom npm i react react-dom - ...

随机推荐

  1. SDNU_ACM_ICPC_2021_Winter_Practice_4th [个人赛]

    传送门 D - Odd Divisor 题意: 给你一个n,问你n是否至少有一个奇数因子(这里题意没说清,没说是不是只有一个还是可以有多个!AC以后才发现是不止一个 思路: 如果这个数没有奇数因子,那 ...

  2. NIO非阻塞网络编程原理

    NIO非阻塞网络编程原理 1.NIO基本介绍 Java NIO 全称 java non-blocking IO,是指 JDK 提供的新 API.从 JDK1.4 开始,Java 提供了一系列改进的 输 ...

  3. 苹果 M1 芯片 OpenSSL 性能测试

    Apple M1(MacBook Air 2020) type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes md2 0.00 0.00 0.00 ...

  4. Win10家庭版Hyper-V出坑(完美卸载,冲突解决以及Device Guard问题)

    本文链接:https://blog.csdn.net/hotcoffie/article/details/85043894 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附 ...

  5. TCP/IP建立连接的时候ISN序号分配问题

    初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(different instantiations/inc ...

  6. ByteDance 2019 春招题目

    牛客网字节跳动笔试真题:https://www.nowcoder.com/test/16516564/summary 分了 2 次做,磕磕碰碰才写完,弱鸡悲鸣. 1. 聪明的编辑 题目:Link . ...

  7. 《进击吧!Blazor!》第一章 3.页面制作

    作者介绍 陈超超Ant Design Blazor 项目贡献者拥有十多年从业经验,长期基于.Net技术栈进行架构与开发产品的工作,Ant Design Blazor 项目贡献者,现就职于正泰集团 写专 ...

  8. 云原生项目实践DevOps(GitOps)+K8S+BPF+SRE,从0到1使用Golang开发生产级麻将游戏服务器—第1篇

    项目初探 项目地址: 原项目:https://github.com/lonng/nanoserver 调过的:https://github.com/Kirk-Wang/nanoserver 这将是一个 ...

  9. Centos7部署FytSoa项目至Docker——第一步:安装Docker

    FytSoa项目地址:https://gitee.com/feiyit/FytSoaCms 部署完成地址:http://82.156.127.60:8000/ 先到腾讯云申请一年的云服务器,我买的是一 ...

  10. python几个练习(素数、斐波那契数列)

    随机输入求素数: x = int(input("please enter the number:")) if x != 1: for i in range(2, x): if x ...