使用USELAYOUTEFFECT REECT的问题

发布于 2025-01-19 20:45:50 字数 1229 浏览 0 评论 0 原文

Hook useEffect 异步运行,通常在 DOM 渲染/安装之后,而 useLayoutEffect 同步运行,在 DOM 渲染/安装之前。

使用我的示例 useEffect,一切正常,并且我得到了所需的结果(我存储用户使用 useRef 输入的先前值)。

但是使用我的示例 useLayoutEffect,我没有得到想要的结果,因为它在我的情况下仅作为 useEffect 工作。我认为它应该首先更新 prevName.current = name 并且仅在渲染后更新,导致与用户输入的值相同。我认为,在这种情况下, prevName.currentname 都应该呈现为相同的值。但这并没有发生。

你能解释一下为什么吗?

这是codesandbox: 沙箱

这是代码:

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 runs asynchronously and usually after the DOM is rendered/mounted, whereas useLayoutEffect runs synchronously and before the DOM is rendered/mounted.

Using my example useEffect, all works fine and I get desired result (I store the previous value that the user has entered using useRef).

But using my example useLayoutEffect, I don't get the wanted result, cause it just works as useEffect in my case. I reckon that it should firstly update prevName.current = name and only after render causing the same value that person has entered. I think, that in that case both prevName.current and name should be rendered as same values. But that doesn't happen.

Can you please explain why?

Here's codesandbox: Sandbox

Here's the code:

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>
  );
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吝吻 2025-01-26 20:45:50

Hook useEffect 异步运行,通常在 DOM 渲染/安装之后,而 useLayoutEffect 同步运行,在 DOM 渲染/安装之前。

它们都发生在将更改放入 DOM 后。布局效果的特殊之处在于,如果您在布局效果期间设置状态,则生成的渲染将同步完成。对于普通效果,如果设置状态,它将很快重新渲染,但不是同步的。如果您从未设置状态(如您的示例中所示),那么您使用哪一个不会产生太大影响。

useLayoutEffect 最常见的应用是,您想要渲染一次,测量 dom 上的内容,然后再次渲染,而不让用户看到 dom 上的临时内容。

Hook useEffect runs asynchronously and usually after the DOM is rendered / mounted, whereas useLayoutEffect runs synchronously and before the DOM is rendered / mounted.

Both of them occur after the changes have been put onto the DOM. What's special about layout effects is that if you set state during the layout effect, the resulting render will be done synchronously. For normal effects, if you set state, it will rerender soon, but not synchronously. If you never set state (as in your example), it's not going to make much difference which one you use.

The most common application of useLayoutEffect is that you want to render once, measure the stuff on the dom, and then render again without the user seeing the temporary stuff you had on the dom.

罗罗贝儿 2025-01-26 20:45:50

检查您的 babel.config.js 将运行时设置为自动:

"plugins": [
  ["@babel/plugin-transform-react-jsx", {
    "runtime": "automatic"
  }]
]

Check that your babel.config.js has the runtime set to automatic:

"plugins": [
  ["@babel/plugin-transform-react-jsx", {
    "runtime": "automatic"
  }]
]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文