我已经看到了这个答案: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开始。
Dan Abramov Link 1,Link 2说使用LayoutEffect有一些缺点。这很好地解释了在哪里可以使用这些给定的Kent C。 Dodds。如果您需要一个示例,可以在Chris上看到它。不要忘记阅读,以了解它们之间的区别。
现在有关使用备忘录。它也有一个drawback。对于我们使用Memo的地方以及使用的地方,可以找到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的原因。
但是如果有一种方法不使用这些 Hook ,那将是完美的。