Setting nested react state with event target

291 views Asked by At

I've been struggling with this for awhile now and I just cant seem to get it working correctly. I'm currently building a project for work that allows franchise owners to change their hours of operations online and I came across the following problem while trying to store state.

Here is the state that I need to upload:

const [storeHours, setStoreHours] = useState<WeeklyRanges>({
    monday: [{ from: '09:00', to: '10:00' }],
    tuesday: [{ from: '09:00', to: '10:00' }],
    wednesday: [{ from: '09:00', to: '10:00' }],
    thursday: [{ from: '09:00', to: '10:00' }],
    friday: [{ from: '09:00', to: '10:00' }],
    saturday: [{ from: '09:00', to: '30:00' }],
    sunday: [{ from: '09:00', to: '14:00' }]
  }); 

And here is the currently solution I am working on:


 const handleChange = (
    e: React.ChangeEvent<{ name: string; checked?: unknown; value?: unknown }>
  ) => {
    const [section, key] = e.target.name.split('.');

    return setStoreHours(
      { ...storeHours, [section]: { ...storeHours[section], [key]: e.target.value } }
    );
  };

This is giving me weird issues such as the following that I cant figure out my way around.

enter image description here

enter image description here

Thanks so much for taking a look!

1

There are 1 answers

4
Shyam On

Since your state is a an Object which has a value as array . es6 spread syntax is not enough to create a new copy of the array . es6 spread syntax is useful only when your values in the objects are primitive.

const myObj = { name: "user1", age: "20" };

You need to deep clone an object whose values are another array or object . You can use lodash cloneDeep method . cloneDeep.

Assuming your name is the combination of something like monday.from .

    const handleChange = (
  e: React.ChangeEvent<{ name: string; checked?: unknown; value?: unknown }>
) => {
  const [section, key] = e.target.name.split('.');
  const newStoredHours = cloneDeep(storedHours);
  // you can mutate this as its a brand new object
  newStoredHours[section][0][key] = e.target.value;

  return setStoreHours(
    newStoredHours
  );
};

Different Deep clone techniques