我已经看到了这个答案: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操作,而是在呈现
我将尝试解释在哪里可以使用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。
但是如果有一种方法不使用这些钩子,它将是完美的。