0

I am learning about react and I have come across a scenario in which the behaviour is not what I expected.

I have a react funcional component like so:

import { Box, Button, Grid, ThemeProvider, createTheme } from '@mui/material';
import './styling/App.css';
import RawPayloadUI from './components/RawPayloadUI';
import FormUI from './components/FormUI';
import { useState } from 'react';
import { Template } from './TemplateExporter';

function App() {

  const testFormFields = {...Template};
  const [currentUI, setCurrentUI] = useState('rawPayloadUI');
  const [formFields, setFormFields] = useState(testFormFields);

  const userInterfaces = ['rawPayloadUI', 'formUI'];

  const uiButtonHandler = e => {
    setFormFields(Template);
    //console.log(formFields);
    setCurrentUI(e.currentTarget.value)
  }

  return (
    <ThemeProvider theme={theme}>
      <div className="App">
        <div className='App-header'></div>
        <Grid id='Form' container sx={{ flexDirection: 'row', height: 'fit-content', marginTop: '1vh', justifyContent: 'center' }} spacing={2}>
            {userInterfaces.map((userInterface, idx) => {
              return (
                <Grid item key={idx}>
                  <Button value={userInterface} onClick={uiButtonHandler}>{userInterface}</Button>
                </Grid>
              )
            })}
          </Grid>
        {currentUI === 'formUI' && <FormUI onChange={setFormFields} formFields={formFields} />}
        {currentUI === 'rawPayloadUI' && <RawPayloadUI />}
      </div>
    </ThemeProvider>
  );
}

export default App;

I am trying to reset the formFields state back to the default value when the user switches to a different interface via the uiButtonHandler() method. But it seems like the values set by the onChange method of the FormUI component are being persisted which indicates to me that the underlying base object (Template) is being mutated.

Im not sure what part of the code is causing this mutation.

Can anyone explain which part of the code is causing the data from the onChange method to interact with the Template.

Diagz
  • 9
  • 1
  • Spread syntax creates a [shallow copy](https://developer.mozilla.org/en-US/docs/Glossary/Shallow_copy), if any of the properties of `Template` are nested objects then they will be prone to mutation. see: [What is the most efficient way to deep clone an object in JavaScript?](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript). (TLDR: `const testFormFields = structuredClone(Template);`) – pilchard May 19 '23 at 17:25
  • I think that half answers it. I am unsure what is causing `testFormFields` to change thus affecting the properties of `Template`. I am only using it to set the default state of `formFields` – Diagz May 19 '23 at 17:32
  • your `uiButtonHandler` is directly setting the state to `Template` which will directly mutate all of the imported object. Did you mean `setFormFields(structuredClone(Template));` – pilchard May 19 '23 at 17:38
  • Thanks for your answer, I would like to clarify. And I apologise If I am missing something. `Template` is being mutated. The values set by the `onChange` method of the `FormUI` component are present in the 'mutated' `Template`. But how is that happening? – Diagz May 19 '23 at 17:48
  • @Diagz he's already explained it 2-3 times, and provided links. It's not clear how much more clear we can be here. Try the other dupe link I added. – Jared Smith May 19 '23 at 17:52
  • 1
    The clarity I was lacking from the answer which I now realize was that when I do `setFormFields(Template)` it is updating `formFields` state to be a reference to the `Template` object, and from that point onwards any changes made to formFields will mutate the base Template. This manifests in the values from the `onChange` method interacting with the `formFields` thus mutating the `Template` Thankyou for your answers. – Diagz May 19 '23 at 19:37

0 Answers0