-1

I'm trying to create a Copy of my existing Object by doing this. Somehow I'm constantly creating a copy by reference and not as a new object.

    const fieldSchema = [
        {
            addressType: '',
            addressSuffix: '',
            addressStreet: '',
            addressPostalcode: '',
            addressLocation: '',
            addressCountry: 'Germany',
        },
    ];

    //State
    const [inputFields, setInputFields] = useState(fieldSchema);


    const handleMenuItemCopy = (event, index) => {
        const fields = [...inputFields];
        console.log('Existing Item(s):', inputFields);
        const duplicatedField = fields.splice(index, 1);
        console.log('Copied Item:', duplicatedField);

        const newFields = [...inputFields, ...duplicatedField];
        console.log(newFields);
        setInputFields(newFields);
    };


return (
    <>
     {inputFields.map((inputField, index) => (
         ...
         <TextField
            id={`addressPostalcode-${index}`}
            name="addressPostalcode"
            variant="outlined"
            label="Postleitzahl"
            className={classes.input}
            onChange={(event) => handleInputChange(event, index)}
            value={inputField.addressPostalcode}
         ></TextField>
         ...
     }

     <Button
       classes={{
         root: classes.buttonBase,
         startIcon: classes.buttonStartIcon,
       }}
       variant="outlined"
       onClick={(event) => handleMenuItemCopy(event, index)}
    >
      Duplicate Fields
    </Button>
  </>
)

Live Example

  1. Input some Data inside any Input
  2. Click Button on Top right
  3. Select Duplizieren (Duplicate)
  4. Edit one Field of the Copy
  5. Changes Immediately take also action in the First Object Field Set.

Edit Object Reference Problem

K.Kröger
  • 97
  • 10
  • 1
    `const duplicatedField = fields.splice(index, 1);` `splice` doesn't *copy* things. – T.J. Crowder Apr 26 '21 at 15:16
  • Also `const fields = [...inputFields];` only does a shallow copy of the array. `fields` and `inputFields` still share the same objects as items in the array. – VLAZ Apr 26 '21 at 15:18

2 Answers2

1

You need to copy the actual object. splice doesn't do that, it just removes it from the array (which I don't think you wanted to do).

This copies the object at index and adds the copy at the end:

const handleMenuItemCopy = (event, index) => {
    // Use the callback form
    setInputFields(fields => {
        // Copy the array; the objects within it are still shared
        fields = [...fields];
        // Copy the one that's at `index` and push at the end
        fields.push({...fields[index]});
        // Return the new array
        return fields;
    });
};

It's a shallow copy, which is usually all you need, but see this question's answers if you need to do a deep copy instead.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

You should copy the content of the duplicatedField array that you can do by changing this line:

const duplicatedField = fields.splice(index, 1);

to:

const duplicatedField = fields
  .splice(index, 1)
  .map(item => ({ ...item }));
Mehran Hatami
  • 12,723
  • 6
  • 28
  • 35