Use case for useLayoutEffect + useState vs useMemo



我已经看到了这个答案: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 操作,而只是在渲染<span>标签之前生成类名以避免闪烁,所以我认为我最好使用useMemo,对吗?

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

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

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

现在在实践中。

选项 1 使用布局效果

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,

减去使用布局效果,1,反图案效果或无意义渲染,添加使用状态,

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

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

最新更新