React hooks editable data table architecture?

Viewed 39
import produce from "immer";

function useEditableRows(initialRows) {
  // initialRows is 50 rows x 10 columns
  const [rows, setRows] = useState(initialRows);

  function setValue(rowId, colId, value) {    
    const newRows = produce(rows, draft => {
      const row = draft.find(row => row.id === rowId);
      row[colId] = value;
    });
    setRows(newRows);
  }
  
  return { rows, setValue };
}

Then the table is rendered and each cell has an edit control. The edit controls call setValue, which rerenders every cell in the table instead of just the cell that was edited.

The problem I think is that the setValue function must be recreated every render and passed to every cell, making the cells all rerender. setValue must be recreated because it relies on rows which was changed.

What can I do here to prevent rerendering everything? Maybe useRef could point to rows, and setValue could rely on the ref, thereby allowing me to wrap setValue with useCallback? Is that too much of a hack?

Should I use a state management tool like Redux instead of hooks for managing rows?

1 Answers

If your only real problem is the reference stability you can use useCallback and the callback notation of your setter so it does not need to access rows:

  const setValue = useCallback(function setValue(rowId, colId, value) {    
    setRows(oldRows => produce(oldRows, draft => {
      const row = draft.find(row => row.id === rowId);
      row[colId] = value;
    }));
  }, [])

But generally: If a parent component rerenders, React rerenders all children even if no props change. You'd have to wrap the children in React.memo to avoid that.

Related