【发布时间】:2021-03-25 19:15:00
【问题描述】:
我有一个Layout组件,里面有一个Table组件,每行都有一个组件Entry。
可以选择每一行,所以稍后我可以通过一个按钮将所有条目发送到 REST 服务,因此每次选择一行时,我都会将其添加到我的状态中。
但是每次状态变化时,我的 Layout 组件都会渲染,渲染表格的每个条目,这让我损失了很多性能和时间。
有没有办法避免重新渲染组件?我试图避免使用类组件。
这个函数触发渲染...
const checkBoxHandler = (index) => {
const actualSelectedCheck = checks[index]
if(!selectedChecks.includes(actualSelectedCheck)){
setSelectedChecks(selectedChecks.concat(actualSelectedCheck))
} else {
const newSelectedChecks = selectedChecks.slice();
const indexOfSelected = selectedChecks.indexOf(actualSelectedCheck)
newSelectedChecks.splice(indexOfSelected, 1);
setSelectedChecks(newSelectedChecks);
}
}
为什么我使用选中的支票作为状态?因为 rest 服务的按钮只有在有 1 个或多个选中的检查时才会呈现。
正在重新渲染的 Mi 布局组件...
const fixedModal = (selectedChecks.length === 0) ? null : <RescueAdminModal selectedChecksLength={selectedChecks.length}/>;
const table =
(error === null) ?
(loading) ? <Spinner />
: <RATable checkboxHandler={checkBoxHandler} checks={checks} /> : null;
return(
<Aux>
<div className="mb-2">Filtros por estado</div>
<RAStates changeStateHandler={stateHandler} />
{table}
{fixedModal}
<div style={{height:'6rem'}} />
</Aux>
)
我的表格组件;
const RATable = (props) => {
const classes = useStyles();
return (
<TableContainer style={{overflowX: "initial"}} className='my-5' component={Paper}>
<Table stickyHeader className={classes.table} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell align="center"><b>Fecha de presentación</b></TableCell>
<TableCell align="center"><b>Bco. emisor</b></TableCell>
<TableCell align="center"><b>Nro. Cheque</b></TableCell>
<TableCell align="center"><b>Cta. emisora</b></TableCell>
<TableCell align="center"><b>Importe</b></TableCell>
<TableCell align="center"><b>Suc. Recep.</b></TableCell>
<TableCell align="center"><b>Nro. Boleta</b></TableCell>
<TableCell align="center"><b>Operatoria</b></TableCell>
<TableCell align="center"><b>Fecha Rescate</b></TableCell>
<TableCell align="center"><b>Estado</b></TableCell>
<TableCell align="center"><b>Fec. Ingreso</b></TableCell>
<TableCell align="center"></TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.checks.map((check, index) => <RACheckEntry checkboxHandler={props.checkboxHandler} check={check} index={index+"nico"}/>)}
</TableBody>
</Table>
</TableContainer>
);
}
我的入口组件;
const RACheckEntry = (props) => {
console.log("render checkentry")
const toggleCheckBox = () => props.checkboxHandler(props.index);
return(
<TableRow key={props.index}>
<TableCell align="center" component="th" scope="row">
{props.check.fecPresentacion}
</TableCell>
<TableCell align="right">{props.check.bcoEmis}</TableCell>
<TableCell align="right">{props.check.nroCheque}</TableCell>
<TableCell align="right">{props.check.ctaEmisora}</TableCell>
<TableCell align="right">{props.check.importe}</TableCell>
<TableCell align="right">{props.check.sucRecep}</TableCell>
<TableCell align="right">{props.check.nroBoleta}</TableCell>
<TableCell align="right">{props.check.oper}</TableCell>
<TableCell align="right">{props.check.fechaRescate}</TableCell>
<TableCell align="right">{props.check.estado}</TableCell>
<TableCell align="right">{props.check.fecIngreso}</TableCell>
{(props.check.estado === A_RESCATAR) ? <Checkbox onChange={() => toggleCheckBox(props.index)} color="primary"/> : null}
</TableRow>
)
在 Nadia 发表评论后编辑:
const checkBoxHandler = React.useCallback(index => {
const actualSelectedCheck = checks[index]
if(!selectedChecks.includes(actualSelectedCheck)){
setSelectedChecks(selectedChecks.concat(actualSelectedCheck))
} else {
const newSelectedChecks = selectedChecks.slice();
const indexOfSelected = selectedChecks.indexOf(actualSelectedCheck)
newSelectedChecks.splice(indexOfSelected, 1);
setSelectedChecks(newSelectedChecks);
}
}, []);
【问题讨论】:
-
您应该包含更多我认为的组件代码,以便它成为可重现的示例。
-
我刚刚添加了我所有的 JSX!
-
你的
TableContainer、Table、TableHead、TableBody、TableRow和TableCell组件来自哪个库? -
他们来自material-ui。
-
您可能希望将
RACheckEntry包裹在React.Memo中,这样它们只会在propss 更改时重新渲染(如果这样做,请确保checkboxHandler是使用useCallback创建的)
标签: javascript reactjs react-hooks material-ui