React useEffect in depth
React useEffect in depth
useEffect

class DogInfo extends React.Component {
controller = null
state = {dog: null}
// we'll ignore error/loading states for brevity
fetchDog() {
this.controller?.abort()
this.controller = new AbortController()
getDog(this.props.dogId, {signal: this.controller.signal}).then(
(dog) => {
this.setState({dog})
},
(error) => {
// handle the error
},
)
}
componentDidMount() {
this.fetchDog()
}
componentDidUpdate(prevProps) {
// handle the dogId change
if (prevProps.dogId !== this.props.dogId) {
this.fetchDog()
}
}
componentWillUnmount() {
// cancel the request on unmount
this.controller?.abort()
}
render() {
return <div>{/* render dog's info */}</div>
}
}
function DogInfo({dogId}) {
const controllerRef = React.useRef(null)
const [dog, setDog] = React.useState(null)
function fetchDog() {
controllerRef.current?.abort()
controllerRef.current = new AbortController()
getDog(dogId, {signal: controllerRef.current.signal}).then(
(d) => setDog(d),
(error) => {
// handle the error
},
)
}
// didMount
React.useEffect(() => {
fetchDog()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
// didUpdate
const previousDogId = usePrevious(dogId)
useUpdate(() => {
if (previousDogId !== dogId) {
fetchDog()
}
})
// willUnmount
React.useEffect(() => {
return () => {
controllerRef.current?.abort()
}
}, [])
return <div>{/* render dog's info */}</div>
}
function usePrevious(value) {
const ref = useRef()
useEffect(() => {
ref.current = value
}, [value])
return ref.current
}
function DogInfo({dogId}) {
const [dog, setDog] = React.useState(null)
React.useEffect(() => {
const controller = new AbortController()
getDog(dogId, {signal: controller.signal}).then(
(d) => setDog(d),
(error) => {
// handle the error
},
)
return () => controller.abort()
}, [dogId])
return <div>{/* render dog's info */}</div>
}
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])
class ChatFeed extends React.Component {
componentDidMount() {
this.subscribeToFeed()
this.setDocumentTitle()
this.subscribeToOnlineStatus()
this.subscribeToGeoLocation()
}
componentWillUnmount() {
this.unsubscribeFromFeed()
this.restoreDocumentTitle()
this.unsubscribeFromOnlineStatus()
this.unsubscribeFromGeoLocation()
}
componentDidUpdate(prevProps, prevState) {
// ... compare props and re-subscribe etc.
}
render() {
return <div>{/* chat app UI */}</div>
}
}
function ChatFeed() {
React.useEffect(() => {
// subscribe to feed
// set document title
// subscribe to online status
// subscribe to geo location
return () => {
// unsubscribe from feed
// restore document title
// unsubscribe from online status
// unsubscribe from geo location
}
})
return <div>{/* chat app UI */}</div>
}
function ChatFeed() {
React.useEffect(() => {
// subscribe to feed
return () => {
// unsubscribe from feed
}
})
React.useEffect(() => {
// set document title
return () => {
// restore document title
}
})
React.useEffect(() => {
// subscribe to online status
return () => {
// unsubscribe from online status
}
})
React.useEffect(() => {
// subscribe to geo location
return () => {
// unsubscribe from geo location
}
})
return <div>{/* chat app UI */}</div>
}
function ChatFeed() {
// NOTE: this is pseudo-code,
// you'd likely need to pass values and assign return values
useFeedSubscription()
useDocumentTitle()
useOnlineStatus()
useGeoLocation()
return <div>{/* chat app UI */}</div>
}
// before. Don't do this!
function DogInfo({dogId}) {
const [dog, setDog] = React.useState(null)
const controllerRef = React.useRef(null)
const fetchDog = React.useCallback((dogId) => {
controllerRef.current?.abort()
controllerRef.current = new AbortController()
return getDog(dogId, {signal: controller.signal}).then(
(d) => setDog(d),
(error) => {
// handle the error
},
)
}, [])
React.useEffect(() => {
fetchDog(dogId)
return () => controller.current?.abort()
}, [dogId, fetchDog])
return <div>{/* render dog's info */}</div>
}
function DogInfo({dogId}) {
const [dog, setDog] = React.useState(null)
React.useEffect(() => {
const controller = new AbortController()
getDog(dogId, {signal: controller.signal}).then(
(d) => setDog(d),
(error) => {
// handle the error
},
)
return () => controller.abort()
}, [dogId])
return <div>{/* render dog's info */}</div>
}
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的更多相关文章
- React useEffect的源码解读
前言 对源码的解读有利于搞清楚Hooks到底做了什么,如果您觉得useEffect很"魔法",这篇文章也许对您有些帮助. 本篇博客篇幅有限,只看useEffect,力求简单明了,带 ...
- React Hooks in depth
React Hooks in depth React Hooks https://reactjs.org/docs/hooks-rules.html https://www.npmjs.com/pac ...
- [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 ...
- React Hooks --- useState 和 useEffect
首先要说的一点是React Hooks 都是函数,使用React Hooks,就是调用函数,只不过不同的Hooks(函数)有不同的功能而已.其次,React Hooks只能在函数组件中使用,函数组件也 ...
- React报错之React Hook useEffect has a missing dependency
正文从这开始~ 总览 当useEffect钩子使用了一个我们没有包含在其依赖数组中的变量或函数时,会产生"React Hook useEffect has a missing depende ...
- React报错之React Hook 'useEffect' is called in function
正文从这开始~ 总览 为了解决错误"React Hook 'useEffect' is called in function that is neither a React function ...
- React 中阻止事件冒泡的问题
在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行. JS 中事件的监听与处理 事件捕获与冒泡 DOM 事件会先后经历 捕获 与 冒泡 两个阶段.捕获即事件沿着 DOM 树由上往下传递,到达 ...
- React hooks实践
前言 最近要对旧的项目进行重构,统一使用全新的react技术栈.同时,我们也决定尝试使用React hooks来进行开发,但是,由于React hooks崇尚的是使用(也只能使用)function c ...
- 【React 资料备份】React Hook
Hooks是React16.8一个新增项,是我们可以不用创建class组件就能使用状态和其他React特性 准备工作 升级react.react-dom npm i react react-dom - ...
随机推荐
- zabbix指定版本自动化安装脚本shell
安装服务端zabbix 有时候要部署一个zabbix各种配置啊贼烦. #!/bin/sh #sleep 10 zabbix_version=4.2.5 ###这里你自定义版本,我要的是4.2.5 za ...
- jquery 数据查询
jquery 数据查询 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...
- 详解SpringMVC
详解SpringMVC 一.什么是MVC? MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范.就是将业务逻辑.数据.显示分离的方法来组织代码. ...
- RPM 和YUM总结
RPM RPM命名: 安装 rpm -ihv 其他常用的选项: 1. 重新安装 --replacepkgs (或者 --force ) 2. 不考虑依赖 --nodeps (不推荐) 升级: 查询: ...
- SQLyog破解30天到期
开始--运行中输入regedit.找到regedit.exe 文件 点击regedit.exe...就把注册表编辑器打开了 我们需要找到记录软件使用实现的数据...找到HKEY-CURRENT ...
- 题解 CF620E 【New Year Tree】
有关dfs序的例题,需要有一定的位运算基础 题面 给定一个树,树上有颜色,将某一子树的颜色统一修改,求子树中颜色的数量 Solution 子树修改,子树求和,dfs序的知识(类似区间修改区间求和) 考 ...
- Spring听课笔记(tg)2
配置Bean -- 配置形式:基于XML 文件的方式, 基于注解的方式 -- Bean的配置方式:通过全类名(反射).通过工厂方法(静态工厂方法&实例工厂方法).FactoryBean -- ...
- logstash的S3 input插件
logstash从AWS S3获取日志信息的常用方法有两种,一种是利用AWS lambda,另一种就是利用logstash的S3 input插件. 插件github:https://github.co ...
- java架构《Socket网络编程基础篇》
本章主要介绍Socket的基本概念,传统的同步阻塞式I/O编程,伪异步IO实现,学习NIO的同步非阻塞编程和NIO2.0(AIO)异步非阻塞编程. 目前为止,Java共支持3种网络编程模型:BIO.N ...
- ubuntu虚拟机重启后进入initramfs的解决办法
问题:windows下使用VMware或者自己安装的ubuntu系统出现,不能正常进入系统,而是进入一个以initramfs开头的命令行界面! 原因:不正常的关闭系统,导致系统文件损坏,/dev/sd ...