我正在尝试使用react-useMemo来防止组件重新呈现。但是不幸的是,它似乎并没有解决任何问题,我开始怀疑自己做错了什么
我的组件看起来像这样
function RowVal(props) {
console.log('rendering');
return (
<Row toggleVals={props.toggleVals}>
<StyledTableData centerCell>{props.num}</StyledTableData>
<StyledTableData centerCell borderRight>
{props.percentage}
</StyledTableData>
</Row>
);
}
为了防止重新渲染-我将以下内容添加到了父组件中
function ChainRow(props) {
const MemoizedRowVal = useMemo(
() => (
<RowVal
num={props.num}
percentage={props.percentage}
toggleVals={props.toggleVals}
/>
),
[props.toggleVals],
);
return (
<div>{MemoizedRowVal}</div>
)
}
但是,即使布尔值没有变化,该组件仍然保持重新渲染。
我在做错什么吗?
答案 0 :(得分:1)
useMemo
将阻止创建组件的新实例,并且如果props不变,也不会阻止其重新呈现
我认为您需要使用React.memo
而不是useMemo
function ChainRow(props) {
return (
<div>
<RowVal
num={props.num}
percentage={props.percentage}
toggleVals={props.toggleVals}
/>
</div>
)
}
const RowVal = React.memo((props) => {
// rowVal code here
});
React.memo
还提供了第二个参数(areEqual),您可以使用它来对重新渲染进行更精细的控制
答案 1 :(得分:1)
在react中,我们通常将React.Memo用于您的用例。将其包装在子组件上。您可能将它与React.useMemo混淆了。他们是不同的。 Using useMemo instead of React.memo syntax issue 检查该答案。
您可以尝试类似的操作
function RowVal(props) {
console.log('rendering');
return (
<Row toggleVals={props.toggleVals}>
<StyledTableData centerCell>{props.num}</StyledTableData>
<StyledTableData centerCell borderRight>
{props.percentage}
</StyledTableData>
</Row>
);
}
export default React.Memo(RowVal).
答案 2 :(得分:0)
您发布的代码没有任何问题,当ChainRow使用相同的道具进行渲染时,也没有RowVal的渲染。我在下面的示例代码段中复制了您的代码,以证明您描述问题中所要执行的代码不是它所执行的工作,并且您的“问题”很可能是由于您未在问题中发布的内容引起的。
const { useState, useMemo } = React;
function RowVal(props) {
console.log('rendering RowVal');
return <pre>{JSON.stringify(props)}</pre>;
}
function ChainRow(props) {
const MemoizedRowVal = useMemo(
() => (
<RowVal
num={props.num}
percentage={props.percentage}
toggleVals={props.toggleVals}
/>
),
[props.num, props.percentage, props.toggleVals]
);
return <div>{MemoizedRowVal}</div>;
}
function App() {
const [state, setState] = useState({
num: 1,
percentage: 1,
toggleVals: 1,
});
console.log('render app (if unrelated will not re render RowVal)');
return (
<div>
<button
onClick={() => setState((state) => ({ ...state }))}
>
unrelated app re render
</button>
<button
onClick={() =>
setState((state) => ({
...state,
num: state.num + 1,
}))
}
>
change num
</button>
<button
onClick={() =>
setState((state) => ({
...state,
percentage: state.percentage + 1,
}))
}
>
change percentage
</button>
<button
onClick={() =>
setState((state) => ({
...state,
toggleVals: state.toggleVals + 1,
}))
}
>
change toggleVals
</button>
<ChainRow
num={state.num}
percentage={state.percentage}
toggleVals={state.toggleVals}
/>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
您的useMemo还缺少会导致stale closures的props.num和props.percentage依赖性。如果您使用create react app创建了应用程序,则linter应该告诉您,因为cra的较新版本具有exhaustive deps