我已经看到了这个答案: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。
但如果有一种方法不使用这些钩子,那将是完美的。