React - Default state

10,191

It is happened because you declare you DEFAULT_STATE object once, and all items stored in memory, and your resetGame only links to this created once object.

But you can make function which will built your state every time.

Example:

const buildState = () => ({
  disabledItems: [],
  wordToGuess: mots[Math.floor(Math.random() * mots.length)],
  mistakes: 0,
  lose: false,
  win: false,
});

class App extends Component {
  constructor(props) {
    super(props)
    this.state = { ...buildState() }
  }

  //Arrow function for binding
  //Restart the game
  resetGame = () => {
    this.setState({ ...buildState() })
  }

After that each call buildState() returns new different object.

Share:
10,191
Jérémy S.
Author by

Jérémy S.

Updated on September 03, 2022

Comments

  • Jérémy S.
    Jérémy S. over 1 year

    I have a question for you about React.

    I'd like to know why my code isn't working correctly :

    const DEFAULT_STATE = {
      disabledItems: [],
      wordToGuess: mots[Math.floor(Math.random() * mots.length)],
      mistakes: 0,
      lose: false,
      win: false,
    }
    
    class App extends Component {
      constructor(props) {
        super(props)
        this.state = { ...DEFAULT_STATE }
      }
    
      //Arrow function for binding
      //Restart the game
      resetGame = () => {
        this.setState({ ...DEFAULT_STATE })
      }
    

    The problem is that my two states disabledItems and wordToGuess are not reset when resetGame is called...

    Instead, this the code that is currently working :

    const DEFAULT_STATE = {
      mistakes: 0,
      lose: false,
      win: false,
    }
    
    class App extends Component {
      constructor(props) {
        super(props)
        this.state = {
          ...DEFAULT_STATE,
          disabledItems: [],
          wordToGuess: mots[Math.floor(Math.random() * mots.length)],
        }
      }
    
      //Arrow function for binding
      //Restart the game
      resetGame = () => {
        this.setState({
          ...DEFAULT_STATE,
          disabledItems: [],
          wordToGuess: mots[Math.floor(Math.random() * mots.length)],
        })
      }
    

    Here, everything do just fine.

    Is it a reference problem ? Please help me to understand :) ! Thanks a lot !

  • Jérémy S.
    Jérémy S. almost 6 years
    Thanks that's what I thought but I couldn't really explain why and how. Is there any performance issue with this method ?
  • Artem Mirchenko
    Artem Mirchenko almost 6 years
    I think it is have not perf issues because, you need to generate new object each time in resetGame method whatever. Or in future you can attach new keys to this object like this: this.setState({ ...buildState(), foo: 1, bar: 'foo' })
  • Jérémy S.
    Jérémy S. almost 6 years
    OK thanks a lot ! And another (and the last) question :) ! Why do my object keeps the reference ? I'm using : this.state = { ...DEFAULT_STATE } - isn't it a real clone ? It shouldn't links to DEFAULT_STATE, am I wrong ?
  • Dominic
    Dominic almost 6 years
    This is because the spread operator only makes a shallow clone. Meaning nested non-primitives are not cloned (AKA your arrays). Generally you don't need deep clones and it's more efficient to do a shallow, but in this case you do need to re-create those nested objects
  • Artem Mirchenko
    Artem Mirchenko almost 6 years
    It’s links to DEFAULT_STATE but it declared once in your bundle and resetGame method grab it old object
  • Jérémy S.
    Jérémy S. almost 6 years
    My state wordToGuess is not reset too, so mots[Math.floor(Math.random() * mots.length)], meaning value generated with function also aren't primitives ?
  • Jérémy S.
    Jérémy S. almost 6 years
    Hi ! In fact, disabledItems isn't reset, same as wordToGuess, that's why I wrote it this way.
  • Artem Mirchenko
    Artem Mirchenko almost 6 years
    Yes, you need to declare DEFAULT STATE as function, because your resetGame must set new wordToGuess to your state all time.
  • roxxypoxxy
    roxxypoxxy almost 6 years
    See this example jsfiddle.net/fhL0cu7p and see if it is any different from your scenario
  • Jérémy S.
    Jérémy S. almost 6 years
    Thanks for sharing :) !