如何控制组件何时渲染? React js 用于向 post 添加评论
How to control when a component renders? React js for adding a comment to a post
https://codesandbox.io/s/busy-paper-w39kvw?file=/src/components/Comments.js:141-200
const initialState = {
comments: [
{
id: 1,
username: "Kevin",
date: "3 hours ago",
text: "Hello",
votes: 12,
upvoted: false,
downvoted: false,
comments: []
}
]
}
在我的评论代码中我有一个useSelector
const { comments } = useSelector(state => state.comments)
每次添加新评论时都会呈现所有评论
如此处所示,使用 React 开发工具添加以在组件呈现时突出显示:https://i.gyazo.com/43a93b6d07a5802d91d9f68684e5ded5.mp4
我尝试使用 React.memo
来记住评论,但我不确定为什么它不起作用。添加评论后是否可以停止呈现所有评论?
当组件被包裹在 React.memo() 中时,React 会渲染组件并记住结果。在下一次渲染之前,如果新的 props 相同,React 会重用记忆的结果,跳过下一次渲染。
在下面的代码中,您将 allComments
函数传递给评论组件。
const allComments = (comments, bg) => {
const output = comments.map((comment) => {
return (
<Comment
key={comment.id}
comment={comment}
allComments={allComments} // the function get's passed as new function object on each rerender
bg={bg}
/>
);
});
return output;
};
what is the problem then and why this behavior?
由于函数相等性检查,javascript中的函数被视为一等公民,换句话说,函数是对象。
function factory() {
return (a, b) => a + b;
}
const sum1 = factory();
const sum2 = factory();
sum1(1, 2); // => 3
sum2(1, 2); // => 3
sum1 === sum2; // => false
sum1 === sum1; // => true
函数sum1和sum2共享相同的代码源,但它们是不同的函数对象。比较它们 sum1 === sum2 计算结果为 false。这就是 Javascript 的工作原理。
在你的代码中,一个新的函数对象 allComments
会在每个渲染中通过 React 创建,最终会作为一个新的 prop 传递给 React.memo()
。默认情况下 React.memo()
对道具和道具对象进行浅表比较。这就是它触发新的重新渲染的原因。
现在我们深刻理解了问题所在以及导致此行为的原因。
解决方案是用 useCallback
包裹你的 allComments
useCallback 的目的是什么?它在渲染之间维护单个函数实例。因此 React.memo()
将起作用。
const allComments = useCallback((comments, bg) => {
const output = comments.map((comment) => {
return (
<Comment
key={comment.id}
comment={comment}
allComments={allComments}
bg={bg}
/>
);
});
return output;
},[]);
https://codesandbox.io/s/busy-paper-w39kvw?file=/src/components/Comments.js:141-200
const initialState = {
comments: [
{
id: 1,
username: "Kevin",
date: "3 hours ago",
text: "Hello",
votes: 12,
upvoted: false,
downvoted: false,
comments: []
}
]
}
在我的评论代码中我有一个useSelector
const { comments } = useSelector(state => state.comments)
每次添加新评论时都会呈现所有评论
如此处所示,使用 React 开发工具添加以在组件呈现时突出显示:https://i.gyazo.com/43a93b6d07a5802d91d9f68684e5ded5.mp4
我尝试使用 React.memo
来记住评论,但我不确定为什么它不起作用。添加评论后是否可以停止呈现所有评论?
当组件被包裹在 React.memo() 中时,React 会渲染组件并记住结果。在下一次渲染之前,如果新的 props 相同,React 会重用记忆的结果,跳过下一次渲染。
在下面的代码中,您将 allComments
函数传递给评论组件。
const allComments = (comments, bg) => {
const output = comments.map((comment) => {
return (
<Comment
key={comment.id}
comment={comment}
allComments={allComments} // the function get's passed as new function object on each rerender
bg={bg}
/>
);
});
return output;
};
what is the problem then and why this behavior?
由于函数相等性检查,javascript中的函数被视为一等公民,换句话说,函数是对象。
function factory() {
return (a, b) => a + b;
}
const sum1 = factory();
const sum2 = factory();
sum1(1, 2); // => 3
sum2(1, 2); // => 3
sum1 === sum2; // => false
sum1 === sum1; // => true
函数sum1和sum2共享相同的代码源,但它们是不同的函数对象。比较它们 sum1 === sum2 计算结果为 false。这就是 Javascript 的工作原理。
在你的代码中,一个新的函数对象 allComments
会在每个渲染中通过 React 创建,最终会作为一个新的 prop 传递给 React.memo()
。默认情况下 React.memo()
对道具和道具对象进行浅表比较。这就是它触发新的重新渲染的原因。
现在我们深刻理解了问题所在以及导致此行为的原因。
解决方案是用 useCallback
allComments
useCallback 的目的是什么?它在渲染之间维护单个函数实例。因此 React.memo()
将起作用。
const allComments = useCallback((comments, bg) => {
const output = comments.map((comment) => {
return (
<Comment
key={comment.id}
comment={comment}
allComments={allComments}
bg={bg}
/>
);
});
return output;
},[]);