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

我正在尝试使用 React memo 组件作为行从头开始创建一个 Table 组件,以防止不必要的重新渲染。rows cells 是一个由子函数创建的 React 组件数组,其中包含行数据、行 id、行索引和 commitChange 函数作为参数。commitChange 函数用于设置行的表状态。这是代码:

表组件.jsx


export 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 否,我不需要外部库来制作自定义表格元素


守着一只汪
浏览 178回答 1
1回答

ABOUTYOU

问题是您正在浅复制 TableData (使用...),因此当您更新此处的值时:newState[index][field] = value...您正在改变数组中的项目,但对该项目的引用保持不变。一种解决方法是这样做:setTableData(prevTableData =>&nbsp; &nbsp; prevTableData.map((item, i) =>&nbsp; &nbsp; &nbsp; i === index ? { ...item, [field]: value } : item,&nbsp; &nbsp; ),&nbsp; )所以现在当字段更新时会创建一个新对象。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript