深入反应 useEffect/useEffect 的使用? [英] React useEffect in depth / use of useEffect?
问题描述
我正在尝试深入了解 useEffect
钩子.
我想知道何时使用哪种方法以及为什么?
1.useEffect 没有第二个参数useEffect(()=>{})2.useEffect 的第二个参数为 []useEffect(()=>{},[])3.useEffect 在第二个参数中传递一些参数useEffect(()=>{},[arg])
useEffect(callback);//例子useEffect(() => {console.log(渲染阶段后执行");返回 () =>{console.log(渲染后的清理功能");};});
- 在每个组件渲染上运行.
- 通常用于调试,类似于函数体在每个渲染:
const Component = () =>{打回来()返回<></>;};
<块引用>
注意:在执行时间方面仍然存在差异(请参阅下一个注意事项).检查这个沙箱日志.
- 清理函数在每次渲染后运行.
useEffect(callback,[]);//例子useEffect(() => {const fetchUsers = async() =>{const 用户 = 等待 fetch();设置用户(用户);};fetchUsers();console.log(调用组件的挂载");返回 () =>{console.log(调用组件的卸载");};}, []);
- 通常用于通过数据获取等方式初始化组件状态
- 在组件安装上运行一次.
- 清理功能将在组件的卸载.
问题:
- 回调在之后渲染阶段执行一>.
记住,有一个第一次渲染,然后然后一个坐骑.
- 由于关闭 导致的陈旧数据
粗略地说,大多数关于 useEffect
的错误是不知道闭包是如何工作的,并且没有注意linting警告.
<块引用>
确保数组包含组件范围内的所有值,这些值随时间变化并被效果使用.否则,您的代码将引用之前渲染中的陈旧值 - React 文档中的注释.
useEffect(callback,[arg]);//例子useEffect(() => {控制台日志({用户});返回 () =>{console.log(用户值正在改变");};}, [用户]);
- 在
arg
值变化时运行. - 通常用于在道具/状态更改时运行事件.
- 可以提供多个依赖:
[arg1,arg2,arg3...]
- 清理函数在
arg
值更改时运行.
问题:
- On Change" 指的是 浅比较 与
arg
的前一个值.
i.e 比较来自前一个渲染和当前渲染的 arg
的值,prevArg === arg ?doNothing() : callback()
.
因为在 Javascript
{} === {} ||[] === []
是一个 falsy 语句,如果arg
(在我们的示例中为users
)是一个对象,则回调将在每次渲染时运行.也在挂载上运行,因为第一次比较总是错误的
其他注意事项
useEffect
回调 在浏览器重新启动后触发-油漆.useEffect
回调按声明顺序执行(像所有钩子),检查示例.- 每个
useEffect
都应该有一个单一责任. - 如果您使用来自
useRef
的值,请在清理函数中事先将该值复制到回调的作用域.
const timeoutIdRef = useRef();useEffect(() => {const timeoutId = timeoutIdRef.current;返回 () =>{/*在这里直接使用 timeoutIdRef.current 是不安全的因为你不能保证在这一点上存在引用(特别是当组件卸载时)*///应该在这里得到一个 lint 警告clearTimeout(timeoutIdRef.current);//坏的//关闭 timeoutId 值clearTimeout(timeoutId);//好的};}, [参数]);
- 当 ref 指向一个 DOM 元素时,使用
ref.current
作为useEffect
的依赖是否安全? - 有时您需要在安装或首次渲染时运行
useEffect
ONCE,这些是常见的模式.
const isMounted = useRef(false);useEffect(() => {如果(isMounted.current){//第一次挂载} 别的 {isMounted.current = true;}}, [参数]);
继续阅读:
- 我的附加答案解释了
useEffect
的return
语句回调 useEffect
完整指南,作者 Dan AbramovuseEffect
API- 使用效果钩子 - React 文档
I am trying to understand the useEffect
hook in-depth.
I would like to know when to use which method and why?
1.useEffect with no second paraments
useEffect(()=>{})
2.useEffect with second paraments as []
useEffect(()=>{},[])
3.useEffect with some arguments passed in the second parameter
useEffect(()=>{},[arg])
useEffect(callback);
// Example
useEffect(() => {
console.log("executed after render phase");
return () => {
console.log("cleanup function after render");
};
});
- Runs on every component render.
- Typically used for debugging, analogous to function's body execution on every render:
const Component = () => {
callback()
return <></>;
};
Note: There is still a difference, in execution time (see the next note). Check this sandbox logs.
- The cleanup function runs after each render.
useEffect(callback,[]);
// Example
useEffect(() => {
const fetchUsers = async () => {
const users = await fetch();
setUsers(users);
};
fetchUsers();
console.log("called on component's mount");
return () => {
console.log("called on component's unmount");
};
}, []);
- Usually used for initializing components state by data fetching etc.
- Runs once on a component mount.
- The cleanup function will run on component's unmount.
Gotchas:
- The callback executed after the render phase.
Remember, there is a first render and then a mount.
- Stale data due to closures
Roughly saying, most of bugs regarding
useEffect
is not knowing how closures works and not paying attention to linting warnings.
Make sure the array includes all values from the component scope that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders - note in React docs.
useEffect(callback,[arg]);
// Example
useEffect(() => {
console.log({ users });
return () => {
console.log("user value is changing");
};
}, [users]);
- Runs on change of
arg
value. - Usually used to run events on props/state change.
- Multiple dependencies can be provided:
[arg1,arg2,arg3...]
- The cleanup function runs on
arg
value change.
Gotchas:
- "On Change" refers to shallow comparison with the previous value of
arg
.
i.e compares the value of
arg
from the previous render and the current one,prevArg === arg ? doNothing() : callback()
.
Because in Javascript
{} === {} || [] === []
is a falsy statement, ifarg
(users
in our example) is an object, the callback will run on every render.Runs on mount too, since the first comparison always falsy
Additional Good to Know Points
useEffect
callbacks fired after browser's re-paint.useEffect
callbacks executed in declaration order (like all hooks), check the example.- Every
useEffect
should have a SINGLE responsibility. - If you using a value from
useRef
, in the cleanup function, copy the value to callback's scope beforehand.
const timeoutIdRef = useRef();
useEffect(() => {
const timeoutId = timeoutIdRef.current;
return () => {
/*
Using timeoutIdRef.current directly here is not safe
since you can't guarantee the ref to exists in this point
(especially when the component unmounts)
*/
// Should get a lint warning here
clearTimeout(timeoutIdRef.current); // BAD
// Closure on timeoutId value
clearTimeout(timeoutId); // GOOD
};
}, [arg]);
- Is it safe to use
ref.current
asuseEffect
's dependency when ref points to a DOM element? - Sometimes you need to run
useEffect
ONCE, on mount or on first render, those are the common patterns.
const isMounted = useRef(false);
useEffect(() => {
if (isMounted.current) {
// first mount
} else {
isMounted.current = true;
}
}, [arg]);
Keep reading:
- My additional answer explaining the
return
statement ofuseEffect
callback - A Complete Guide to
useEffect
by Dan Abramov useEffect
API- Using the effect hook - React docs
这篇关于深入反应 useEffect/useEffect 的使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!