I'm trying to create a Table component from scratch using React memo component as rows to prevent unecessary re-rendering. The rows cells is an array of React components created from a children function with row data, row id, row index and a commitChange function as parameters. The commitChange function is used to set the Table state from a row. This is the code:
<Table data={[{name: 1}, {name: 2}]}> {({data, index, id, commitChange})=> [ <div>Name: {data.name}</div>, <TextBox value={data.name} onChange={(value)=>commitChange('name', parseInt(value, 10))}/>, <TextBox value={data.place}/> ] } </Table> TableComponents.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> ) }) When an element was added to the data props on the Table component the table re-render and render only the added row and this works ok.
But when a row element is edit from the textbox in the second cell the data on the parent Table component was correctly updated but the row not re-render. When I check the previus and next proprieties passed to component with React.memo areEqual function (Documentation here) the data proprieties is the same. The table component is re-render when TableData is update by row and the renderRows function is executed but without re-render of the updated row.
What is the problem? Thanks for help
P.S No I don't want an external library to make custom Table elements