0
votes

I am using react-table to build a sortable list of forms. In this example, each form has a checkbox for approved, a textfield for the name, and a send button. After clicking the send button, the form should be removed from the DOM. The problem is that when removing the first row, the checkbox in the second row takes the state of the first row. The text field maintains its value.

I am using uncontrolled form components to display the data, but I am using the handleChange method to update the top-level data array.

Here is a code sandbox to reproduce the issue. https://codesandbox.io/s/unruffled-williamson-d172s

Repro steps:

  1. Check the checkbox in the first row.
  2. Enter some text in the checkbox in the first row.
  3. Hit send in the first row.

Expected results: The first row should be removed.

Actual results: The first row is removed and the remaining checkbox is checked.

Would anyone be able to explain why the checkbox is checked after removing the first row? I think it might be because the key is based on the index, meaning, after the first row is removed, the second row's key is same as the first row. Is there a way to customize the react-table key? If the key is the reason though, I am confused as to why only the checkbox copies the previous value and not the text box.

1

1 Answers

0
votes

I solved this by changing the key react-table used. This can be done either by adding a hook to react-table or implementing the getRowID method.

Using getRowID and a key value combination for the hash

const getRowID = (row, relativeIndex) => {
  const hash = Object.keys(row).map(k => {
    // Only get the first letter of the prop and value
    // to keep the hash short, so it is easier to see
    // the full hash in dev tools
    return `${k[0]}${String(row[k])[0] || ''}`;
  }).join('');
  const id = `${relativeIndex}${hash}`;
  return id;
};
const table = useTable({ columns, data, getRowID });

useTable documentation with the getRowID function

Using hooks and Math.random for the hash

// Using Math.random() will usually guarantee a unique hash
// but it is better to get a hash function that would map
// the same row to the same hash
const keyHooks = hooks => {
  hooks.getRowProps.push(props => {
    return {
      key: `${props.index}_${Math.random()}`
    }
  });
};

// ...

const table = useTable({ columns, data }, keyHooks);