React hook useState mutates a constant array

  arrays, javascript, react-hooks, reactjs

I’m using React hooks to implement a form. The state of the form is being managed as an array of objects. A feature/bug of React appears to be that copies of arrays are processed/unified/mutated as a single array. That is, changes to one array become changes in all copies of the array.

I do not want to mutate the array as it creates an issue when attempting to use an array to initialize and reset the state. Once the initialization array becomes unified with the state array, the reset function will no longer work. I have made some attempts at preventing array unification without success. Below is the problem, some of my attempts to resolve the issue and a work around.

Lets say the state of the form is defined as:

const [field, setField] = useState(initialField);

Once this code executes, the value of array initialField is unified with the value of the array field.

Lets say we want to reset the form and use a function like this:

const reset = () =>{setField(initialField)}

This reset function will not work. Once the value of initialField is unified to the current value of field, setField will always contain the current value of field.

Lets say we replace initialField with:

initialField.map((e)=>{return e;})

The map method is immutable. It should create a separate array. However, replacing initialField with a map method of initialField does not change the result. useState still unifies the value of initalField with field.

Using the separator operator, {…intialField}, does not change the outcome. Neither does using intialField.concat(). Lets say we assign initalField to another array resetField. React will unify together all three arrays: field, initialField and resetField.

Lets say we hard code the array into the setState function. Assuming we have an array of N objects, it would look something like:

const [field, setField] = useState([{object 0}, {object 1} ... {object N}] );

The reset function is still:

const reset = () =>{setField(initialField)}

The reset function will work exactly once. Once the code is executed, React unifies initialField with field, so the reset function will no longer work. Lets say we replace initalField with a map method, a separator operator or a concat method. React will still unify the field array with initialField.

A work around this is to hard code the array into the setState and the reset functions as follows:

const [field, setField] = useState([{Object 0},{Object 1},...{Object N}]);

const reset = () =>{setField([{Object 0},{Object 1},...{Object N}])};

This is an ugly solution that complicates maintenance as the same changes have to be made twice.

Source: Ask Javascript Questions

LEAVE A COMMENT