Hook useEffect 异步运行,通常在 DOM 渲染/安装之后,而 useLayoutEffect 同步运行,在 DOM 渲染/安装之前。
使用我的示例 useEffect,一切正常,我得到了所需的结果(我存储用户使用 useRef 输入的先前值)。
但是使用我的示例 useLayoutEffect,我没有得到想要的结果,因为它在我的情况下仅作为 useEffect 工作。我认为它应该首先更新
prevName.current = name
并且仅在渲染后更新,导致与用户输入的值相同。我认为,在这种情况下 prevName.current
和 name
都应该呈现为相同的值。但这并没有发生。
你能解释一下为什么吗?
这是代码和盒子:沙盒
这是代码:
import React, { useLayoutEffect } from "react";
import "./styles.css";
import { useState, useRef, useEffect } from "react";
export default function App() {
const [name, setName] = useState("");
const prevName = useRef(name);
useLayoutEffect(() => {
prevName.current = name;
}, [name]);
return (
<div className="App">
<input
value={name}
onChange={(e) => {
setName(e.target.value);
}}
></input>
<div>Your name is {name}</div>
<div>Your previous name is {prevName.current}</div>
</div>
);
}
Hook useEffect 异步运行,通常在 DOM 渲染/挂载之后,而 useLayoutEffect 同步运行,在 DOM 渲染/挂载之前。
这两者都发生在将更改放入 DOM 之后。布局效果的特殊之处在于,如果您在布局效果期间设置状态,则生成的渲染将同步完成。对于普通效果,如果设置状态,它将很快重新渲染,但不是同步的。如果您从未设置状态(如您的示例中所示),那么您使用哪一个不会有太大区别。
useLayoutEffect 最常见的应用是,您想要渲染一次,测量 dom 上的内容,然后再次渲染,而不让用户看到 dom 上的临时内容。
检查你的 babel.config.js 是否将运行时设置为自动
“插件”:[ [“@babel/plugin-transform-react-jsx”,{ “运行时”:“自动” }]