React Hooks文章发布/取消发布后视图更新问题求助
问题分析与解决方案
这个问题的核心在于React useState的更新是异步的——当你调用setIndexNumStatus(i)之后,indexNumStatus并不会立刻变成最新值,所以紧接着执行const newArrayList = Object.assign([...rowsData], {[indexNumStatus]: d});时,indexNumStatus还是之前的旧值(初始是0),这就导致第一次点击时替换的是索引0的项,第二次点击时才会用上一次正确的索引,出现视图更新异常。
而且你完全不需要额外维护indexNumStatus这个状态,直接在API回调里处理数组更新即可,推荐两种更可靠的方式:
方案1:使用函数式更新+数组map(最简洁)
利用setRowsData的函数式更新特性(接收当前最新的状态作为参数),直接遍历数组替换目标项,不需要手动找索引:
// ListSections.js const ListSections = ({ sectionData }) => { const [rowsData, setRowsData] = React.useState(sectionData); /* ** @@ ** @@ PUBLISHED / UNPUBLISHED ** @@ */ const renderStatusButton = (status, s_id) => ( <div onClick={() => handleStatusOnClick(status, s_id)}> <Status status={status} /> </div> ); const handleStatusOnClick = (status, s_id) => { const changedStatus = status === STATUS.PUBLISHED ? STATUS.UNPUBLISHED : STATUS.PUBLISHED; const data = { "section": { "status": changedStatus } }; api .put(URLS.CHANGE_COURSE_SECTION(course_id, s_id), data) .then(({ data }) => { const updatedSection = data.data; // 使用函数式更新,确保拿到最新的rowsData setRowsData(prevRows => { return prevRows.map(row => row.id === updatedSection.id ? updatedSection : row ); }); }) .catch(({ response }) => { // 错误处理逻辑 }); }; return ( <TableContainer component={Paper}> <Table className={classes.table} aria-label="simple table"> <TableHead></TableHead> <TableBody> {rowsData.map((row, index) => ( <TableRow key={row.id}> {/* 建议用row.id作为key,比index更可靠 */} <TableCell align="left">{row.attributes.title}</TableCell> <TableCell align="center"> {row.attributes.status}<br /> {renderStatusButton(row.attributes.status, row.id)} </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> ); }; export default ListSections;
方案2:手动找到索引后替换(适合需要额外处理索引的场景)
如果你确实需要用到索引,也可以在回调里直接从当前的rowsData中找到目标项的索引,然后创建新数组:
// 在API的then回调里替换这段代码: .then(({ data }) => { const updatedSection = data.data; const targetIndex = rowsData.findIndex(row => row.id === updatedSection.id); if (targetIndex !== -1) { const newRowsData = [...rowsData]; newRowsData[targetIndex] = updatedSection; setRowsData(newRowsData); } })
额外优化点
- 把
TableRow的key从index改成row.id,因为当数组项顺序变化时,用索引作为key会导致React复用错误的组件,影响性能和状态正确性。 - 移除了不必要的
indexNumStatus状态,减少状态维护的复杂度。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

