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 - ...
随机推荐
- 解决JavaScript中构造函数浪费内存的问题!
解决JavaScript中构造函数浪费内存的问题! 把构造函数中的公共的方法放到构造函数的原型对象上! // 构造函数的问题! function Gouzaohanshu(name, age, gen ...
- 解决 win10 无法安装VS2019,visual studio installer下载进度始终为0
解决 win10 无法安装VS2019,visual studio installer下载进度始终为0 目录 解决 win10 无法安装VS2019,visual studio installer下载 ...
- https://github.com/golang/go/wiki/CommonMistakes
CommonMistakes https://golang.org/doc/faq#closures_and_goroutines Why is there no goroutine ID? ¶ Go ...
- LOJ10099矿场搭建
HNOI 2012 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖 ...
- loj10153二叉苹果树
有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点.这棵树共 N 个节点,标号 1 至 N,树根编号一定为 1. 我们用一根树枝两端连接的节点编号描述一根树枝的位置.一棵有四根树 ...
- 关于MongoDB的简单理解(三)--Spring Boot篇
一.前言 Spring Boot集成MongoDB非常简单,主要为加依赖,加配置,编码. 二.说明 环境说明: JDK版本为15(1.8+即可) Spring Boot 2.4.1 三.集成步骤 3. ...
- Java——继承,重载,重写三剑客
About-继承 所有Java的类均是由java.lang.Object类继承而来的,所以Object是所有类的祖先类,而除了Object外,所有类必须有一个父类. 继承可以理解为一个对象从另一个对象 ...
- Java8中流的性能
流(Stream)是Java8为了实现最佳性能而引入的一个全新的概念.在过去的几年中,随着硬件的持续发展,编程方式已经发生了巨大的改变,程序的性能也随着并行处理.实时.云和其他一些编程方法的出现而得到 ...
- redis学习教程五《管道、分区》
redis学习教程五<管道.分区> 一:管道 Redis是一个TCP服务器,支持请求/响应协议. 在Redis中,请求通过以下步骤完成: 客户端向服务器发送查询,并从套接字读取,通常以阻 ...
- Hive 报错
hadoop hive任务失败,原因是GC overhead limit exceeded (OOM) GC Overhead Limit Exceeded error是java.lang.OutOf ...