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.
Author by
Jérémy S.
Updated on September 03, 2022Comments
-
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. almost 6 yearsThanks that's what I thought but I couldn't really explain why and how. Is there any performance issue with this method ?
-
Artem Mirchenko almost 6 yearsI 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. almost 6 yearsOK 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 almost 6 yearsThis 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 almost 6 yearsIt’s links to DEFAULT_STATE but it declared once in your bundle and resetGame method grab it old object
-
Jérémy S. almost 6 yearsMy 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. almost 6 yearsHi ! In fact, disabledItems isn't reset, same as wordToGuess, that's why I wrote it this way.
-
Artem Mirchenko almost 6 yearsYes, you need to declare DEFAULT STATE as function, because your resetGame must set new wordToGuess to your state all time.
-
roxxypoxxy almost 6 yearsSee this example jsfiddle.net/fhL0cu7p and see if it is any different from your scenario
-
Jérémy S. almost 6 yearsThanks for sharing :) !