【问题标题】:Use case for useLayoutEffect + useState vs useMemouseLayoutEffect + useState 与 useMemo 的用例
【发布时间】:2019-11-23 15:17:07
【问题描述】:

我已经看到了这个答案:useMemo vs. useEffect + useState,它对useEffect 进行了很好的总结,但就我而言,我想执行一项昂贵的操作,以便尽早更改 DOM。是否仍会推荐 useMemo() 而不是 useLayoutEffect() 进行状态更新?双重渲染效果 -> 状态更新是否会抵消任何性能提升?

编辑

useLayoutEffect()场景:

useLayoutEffect(() => {
    const tokens = expensiveOperationGeneratingClasses(param1)
    setTokens(tokens)
}, 
[param1])

 render (
  <>
   {
       tokens.map(token => <span className={token.id}/>)
   }
  </>
 )

useMemo场景:

const tokens = useMemo(() => {
     return expensiveOperationGeneratingClasses(param1)
},
[param1]

 render (
  <>
   {
       tokens.map(token => <span className={token.id}/>)
   }
  </>
 )

实际上我意识到我不是在做 DOM 操作,而只是在渲染 &lt;span&gt; 标签之前生成类名以避免闪烁,所以我认为我最好使用 useMemo,对吗?

【问题讨论】:

  • 你要执行什么具体操作?
  • 我想在对文本进行大量正则表达式操作后更改&lt;span&gt;标签的类名。
  • 请举例说明。
  • @PFuster 你的计算和道具有关吗?
  • @PFuster 是的,你是对的。使用 useMemo。

标签: reactjs react-hooks


【解决方案1】:

我将尝试解释您可以在哪里使用 LayoutEffect 和 Memo。让我们从 LayoutEffect 的使用开始。

Dan Abramov Link 1, Link 2 说 LayoutEffect 的使用有一些缺点。这是一个很好的解释,你可以在哪里使用这些给 Kent C。 Dodds。如果你需要一个例子,你可以在这里看到它Chris。不要忘记阅读以了解差异。

现在关于使用备忘录。它还有一个drawback。关于我们使用备忘录的内容,以及使用它的地方,您可以找到here

现在正在实践中。

选项 1 使用 LayoutEffect

import React, { useState, useLayoutEffect } from "react";
import ReactDOM from "react-dom";

import "./styles.css";
const Control = () => {
  const [add, setAdd] = useState(1);
  return (
    <div>
      <div>
        <PostOffice add={add} />
      </div>
      <div onClick={() => setAdd(add + 1)}>{"Click"}</div>
    </div>
  );
};

function PostOffice({ add }) {
  const [letter, setLetter] = useState(add);

  useLayoutEffect(() => {
    console.log("useLayoutEffect");
    setLetter(add);
  }, [add]);

  console.log(letter);
  return <div className="App">{console.log(letter, "DOM")}</div>;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Control />, rootElement);

我不确定这个选项 1,因为这里有一个 anti-pattern effect

选项 2 使用 LayoutEffect

import React, { useState, useLayoutEffect } from "react";
import ReactDOM from "react-dom";

import "./styles.css";
const Control = () => {
  const [add, setAdd] = useState(1);
  return (
    <div>
      <div>
        <PostOffice add={add} />
      </div>
      <div onClick={() => setAdd(add + 1)}>{"Click"}</div>
    </div>
  );
};

function PostOffice({ add }) {
  const [letter, setLetter] = useState(0);

  useLayoutEffect(() => {
    console.log("useLayoutEffect");
    setLetter(add);
  }, [add]);

  console.log(letter);
  return <div className="App">{console.log(letter, "DOM")}</div>;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Control />, rootElement);

会有无意义的渲染

选项 useMemo

import React, { useState, useMemo } from "react";
import ReactDOM from "react-dom";

import "./styles.css";
const Control = () => {
  const [add, setAdd] = useState(1);
  return (
    <div>
      <div>
        <PostOffice add={add} />
      </div>
      <div onClick={() => setAdd(add + 1)}>{"Click"}</div>
    </div>
  );
};

function PostOffice({ add }) {
  const Letter = useMemo(() => {
    console.log("useMemo");
    return add + 1;
  }, [add]);

  console.log(Letter);
  return <div className="App">{console.log(Letter, "DOM")}</div>;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Control />, rootElement);

这里一切正常

总计

减去 useMemo 1,

减去useLayoutEffect,1,反模式效果或无意义渲染,添加useState,

这就是你应该使用 useMemo 的原因。

但如果有办法不使用这些钩子,那就完美了。

【讨论】:

    猜你喜欢
    • 2019-09-25
    • 2019-12-31
    • 1970-01-01
    • 2019-10-14
    • 2019-08-20
    • 1970-01-01
    • 2020-04-11
    • 2021-06-27
    • 2023-03-25
    相关资源
    最近更新 更多