为了账号安全,请及时绑定邮箱和手机立即绑定

如果 props 改变,React.memo 不会重新渲染

如果 props 改变,React.memo 不会重新渲染

守着一只汪 2023-08-10 15:30:42
我正在尝试使用 React memo 组件作为行从头开始创建一个 Table 组件,以防止不必要的重新渲染。rows cells 是一个由子函数创建的 React 组件数组,其中包含行数据、行 id、行索引和 commitChange 函数作为参数。commitChange 函数用于设置行的表状态。这是代码:表组件.jsxexport const Table = ({ data: initialData, maxRows = 10, children: makeChildren, primaryKey = 'ID' }) => {const [TableData, setTableData] = useState(initialData);console.log('table re-render')useEffect(() => {    console.log('--->table data', TableData)}, [TableData]);useEffect(() => {    setTableData(initialData)}, [initialData]);const renderCells = useCallback((param) => {    return makeChildren(param)}, [])const commitChange = useCallback((field, value, index) => {    setTableData(prevTableData => {        const newState = Array.from(prevTableData)        newState[index][field] = value        return [...newState]    })}, [])const renderRows = () => {    return TableData.map((row, i) =>        <TableRow            key={row[primaryKey]}            index={i}            rowData={row}            cells={renderCells}            id={row[primaryKey]}            updateTableData={commitChange}        />    )}//return (    <table>        <tbody>            {                renderRows()            }        </tbody>    </table>  );}const TableRow = React.memo(({ index, rowData, cells, id, updateTableData }) => {console.log('render row' + index, rowData)useEffect(() => {    console.log('row ' + index + ' data', rowData)}, [rowData])const renderCells = () => {    return cells({ data: rowData, index, id, commitChange: (field, value) => updateTableData(field, value, index) }).map((c, i) => {        return (            <td key={i}>                {c}            </td>        )    })}return (    <tr>        {renderCells()}    </tr>)})当一个元素被添加到 Table 组件上的 data props 时,表会重新渲染并仅渲染添加的行,这样就可以正常工作。但是,当从第二个单元格中的文本框中编辑行元素时,父表组件上的数据已正确更新,但行未重新呈现。当我使用 React.memo areEqual 函数(此处的文档)检查传递给组件的上一个和下一个属性时,数据属性是相同的。当 TableData 按行更新并且执行 renderRows 函数但不重新渲染更新的行时,表组件将重新渲染。问题是什么?感谢帮助PS 否,我不需要外部库来制作自定义表格元素
查看完整描述

1 回答

?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

问题是您正在浅复制 TableData (使用...),因此当您更新此处的值时:


newState[index][field] = value

...您正在改变数组中的项目,但对该项目的引用保持不变。一种解决方法是这样做:


setTableData(prevTableData =>

    prevTableData.map((item, i) =>

      i === index ? { ...item, [field]: value } : item,

    ),

  )

所以现在当字段更新时会创建一个新对象。


查看完整回答
反对 回复 2023-08-10
  • 1 回答
  • 0 关注
  • 177 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信