Reputation: 59
I'm making a simple card game. I want to update the data in state, but the data I keep in data is being updated, how can I solve this problem? I have the right to click 2 times in the game and when similar cards are matched, they disappear. I can't refresh when all cards are matched
I can match the same cards, but I cannot restart when I want to restore them, and when I examine them, I cannot update the data in the state. So in short my reset function doesn't work
my AllCards component
import * as React from 'react'
import { Card } from './components/Card'
import { cardState, ICard } from './Types'
import {data} from './data'
interface IState {
cards: ICard[]
}
class AllCards extends React.Component<{}, IState>{
selectedCardIds: number [] = [];
selectedCards: ICard[] = []
state: IState= {
cards: [...data]
}
cardClickHandler = (card: ICard) =>{
const {cards} =this.state
if (this.selectedCardIds.length< 2){
this.selectedCardIds.push(card.id)
this.selectedCards.push(card)
this.setState({
...this.state,
cards: cards.map(c => c.id === card.id ? card: c)
}, this.checkMarch)
}
//console.log({card});
}
checkMarch = () =>{
if (this.selectedCardIds.length === 2 ){
setTimeout(() => {
let newCards: ICard[] = []
const {cards} =this.state
let nextState: cardState = "unmatched"
if(this.selectedCards[0].content === this.selectedCards[1].content){
nextState = "matched"
}
newCards = cards.map(c=>{
if(this.selectedCardIds.includes(c.id)){
c.state = nextState
}
return c
})
this.selectedCardIds= []
this.selectedCards= []
this.setState({
...this.state,
cards: newCards
})
}, 500);
}
}
reset = () =>{
console.log("reset");
this.selectedCardIds = []
this.selectedCards = []
this.setState({
...this.state,
cards: data
})
}
render() {
const cardList = this.state.cards.map(c => (<Card key={c.id} card={c} clickHandler={this.cardClickHandler}/>))
return (
<div className='container p-3 bg-dark-gray'>
<div className="row row-cols-1 row-cols-md-3 g-4" style={{columnCount:2}}>
{cardList}
</div>
<hr />
<button onClick={this.reset} className='btn btn-primary'> retyrn</button>
</div>
)
}
}
export {AllCards}
Upvotes: 0
Views: 40
Reputation: 638
If the data you're trying to update is one level deep (i.e., doesn't contain any nested objects or arrays), Talha's answer will work. However, if your data is more than one level deep, you run the risk of accidentally mutating the child object. For example,
const test1 = {
a: 1,
b: 2,
c: {
d: 4,
},
};
// Direct assignment
const test2 = test1;
test2.a = 5;
console.log(test1.a, test2.a); // 5, 5
// Assigning via spreading (shallow cloning)
const test3 = { ...test1 };
test3.b = 7;
console.log(test1.b, test3.b); // 2, 7
test3.c.d = 9;
console.log(test1.c.d, test3.c.d); // 9, 9
This answer describes how to deeply clone an object, which will resolve the above issue.
If you want a quick and dirty way to deep-clone an object, you can use JSON.parse
and JSON.stringify
like so:
const test1 = {
a: 1,
b: 2,
c: {
d: 4,
},
}
// Assignment via stringifying/de-stringifying (deep cloning)
const test2 = JSON.parse(JSON.stringify(test1));
test2.c.d = 9;
console.log(test1.c.d, test2.c.d); // 4, 9
Upvotes: 1
Reputation: 402
if you want to get rid of the reference just spread it like
data = {..state.data} // if its object,
data = [...state.data] // if its array
therefore if your state.data gets updated, data will not going to get affected by the changes
Upvotes: 1