首页 > 解决方案 > 如何防止使用 useState 的 React const 的 reRender

问题描述

我试图阻止在 React 功能组件中重新渲染,但不确定如何或实现什么来实现这一点。阅读建议使用备忘录,但我不明白如何在这里实现它。

道具包括'selectAll'(propType = boolean),onSelected是一个回调函数,我使用stateHook进行选择。

因此,如果调用 'setSelected(newSelects)' 方法,它会进入无限的 reRender 循环;我有一个关于返回标记的工作,它有效,但我更愿意使用、学习和理解管理 React 的状态。

代码:

function OptimiserTableBody(props) {
    const {Id, columns, send, onSelected, selectAll} = props;
    const [selected, setSelected] = useState([]);

    // Retrieve the data 
    const resOData = useQuery(o_data_query, {
    variables: {
        id: id,
        use: use
    },
    fetchPolicy: 'cache-and-network'
});

// Create an array from the retrieved data for the table, this is used to create the table rows
let steps = resOData.data != undefined ?  resOData.data.jobO.data : [];

 useEffect(() => {
    if (selectAll === true) {
        let newSelects = steps.map((n) => n.workStepId);
        setSelected(newSelects);
    }
}, [selectAll])


 return (
     <TableBody>
         {steps.map((step, index) => (
             let isItemSelected = isSelected(step.workStepId);
             
             // Workaround
             if (selectAll === true)
             {
                 isItemSelected = true;
             }
             return (
                 <TableRow ... >

                    <TableCell  key={'select'}  padding="checkbox"  >
                        <Checkbox 
                            checked={isItemSelected}
                             inputProps={{ 'aria-labelledby': step.workStepId }}
                                            style={{color: kbaColors.grey1}}
                                            onClick={(event) => handleClick(event, step.workStepId)}
                        />
                    </TableCell>
               </TableRow>
         ))}
      </TableBody>
    );
}
export default React.memo(OptimiserTableBody);

谢谢

标签: reactjsreact-hooksstaterenderingrerender

解决方案


由于您setSelected在每次渲染时,组件都会按照您所说的重新渲染,并进入无限循环。我相信你想更新selected基于selectAll. 您可以在 a 内执行此操作useEffect

import {useEffect} from 'react'

useEffect(() => {
  if(selectAll){
    let newSelects = steps.map((n) => n.workStepId);
    setSelected(newSelects);
  }
}, [selectAll, steps])

通过提供selectAll依赖数组,您可以确保它useEffect仅在selectAll更改时运行。

更新

我注意到您需要steps用作状态变量。所以你可以有两个单独的useEffects

 const [selected, setSelected] = useState([]);
 const [steps, setSteps] = useState([]);
 useEffect(() => {
    const resOData = useQuery(o_data_query, {
    variables: {
        id: id,
        use: use
    },
    fetchPolicy: 'cache-and-network'
    setSteps(resOData.data != undefined ? resOData.data.jobO.data : [])
 }, [] )   

空的依赖数组确保useEffect在组件挂载时只运行一次。在另一个之前添加这个useEffect,你应该很高兴


推荐阅读