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 - ...
随机推荐
- elasticsearch从开始到永久
0.学习目标 独立安装Elasticsearch 会使用Rest的API操作索引 会使用Rest的API查询数据 会使用Rest的API聚合数据 掌握Spring Data Elasticsearch ...
- 淘宝APP消息推送模型
为什么到了2020年,"统一推送联盟"依旧无法起显著作用? - 知乎 https://www.zhihu.com/question/370632447 https://mp.wei ...
- Service Mesh架构的持续演进 单体模块化 SOA 微服务 Service Mesh
架构不止-严选Service Mesh架构的持续演进 网易严选 王育松 严选技术团队 2019-11-25 前言同严选的业务一样,在下层承载它的IT系统架构一样要生存.呼吸.增长和发展,否则过时的.僵 ...
- 大白话入门 Spring Cloud
首先我给大家看一张图,如果大家对这张图有些地方不太理解的话,我希望你们看完我这篇文章会恍然大悟. 什么是Spring cloud 构建分布式系统不需要复杂和容易出错.Spring Cloud 为最常见 ...
- loj1011愤怒的牛
题目描述 原题来自:USACO 2005 Feb. Gold 农夫约翰建造了一座有 n 间牛舍的小屋,牛舍排在一条直线上,第 i 间牛舍在 x_i 的位置,但是约翰的 m 头牛对小屋很不满意,因此经常 ...
- 基于navicat的数据库导入导出
1.右键当前数据库,选择转储SQL文件 选择导出sql的存放路径 2.新建统一命名的数据库,右键运行SQL文件 3,.选择要导入的SQL文件后如图
- 函数式编程(__slots__)
正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: class Student(object): pa ...
- linux shell 条件判断if else, if elif else....
在linux的shell中 if 语句通过关系运算符判断表达式的真假来决定执行哪个分支.Shell 有三种 if ... else 语句: if ... fi 语句: if ... else ... ...
- Linux slabtop命令——显示内核片缓存信息
Linux内核需要为临时对象如任务或者设备结构和节点分配内存,缓存分配器管理着这些类型对象的缓存.现代Linux内核部署了该缓存分配器以持有缓存,称之为片.不同类型的片缓存由片分配器维护. slabt ...
- 【poj 2478】Farey Sequence(数论--欧拉函数 找规律求前缀和)
题意:定义 Fn 序列表示一串 <1 的分数,分数为最简分数,且分母 ≤n .问该序列的个数.(2≤N≤10^6) 解法:先暴力找规律(代码见屏蔽处),发现 Fn 序列的个数就是 Φ(1)~Φ( ...