提问者:小点点

useLayoutEffect useState与UseMoom的用例


我已经看到了这个答案:useMemo vs.Useffect useState,它对Useffect进行了很好的总结,但在我的例子中,我希望执行一个昂贵的操作,尽早改变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操作,而是在呈现


共1个答案

匿名用户

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

Dan Abramov Link 1, Link 2表示,使用Layout效应有一些缺点。这是一个很好的解释,你可以使用这些给肯特C.多德。如果你需要一个例子,你可以在这里看到它,克里斯。不要忘记阅读来理解区别。

现在关于使用备忘录。它也有一个缺点。对于我们使用的备忘录,以及它的使用地点,您可以在这里找到。

现在在实践中。

选项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,因为这里有一个反模式的效果。

选项2使用布局效果

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

这将是一个毫无意义的渲染

选项使用备忘录

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

在这里,一切都很完美

共计

减去备忘录1,

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

这就是为什么你应该使用useMemo。

但是如果有一种方法不使用这些钩子,它将是完美的。

相关问题