Charlotte Cheng
Charlotte Cheng

Reputation: 37

React children component not re-rendering after parent state changes

I am new to React and am trying to create a simple card game. When a card is clicked, it should be selected and assigned a classname of " selectedCard". So when it re-renders, the selected card will be lifted up. However, the selected card did not lift up onClick, my guess is that it did not re-render.

Here is my code snippet:

Player.js:

const Player = (props) =>{
    const [selectedCards, setSelectCard] = useState([]);

    const selectCard = (card) => {
        let newSelectedCards = selectedCards
        if(newSelectedCards.includes(card) ) {
            newSelectedCards.splice(newSelectedCards.indexOf(card), 1)
        } else {
            newSelectedCards.push(card)
        }
        setSelectCard(newSelectedCards)
        console.log('changed');
    }


    return(
            <div className="player-container">
                {props.cards && props.cards.map((card, i) => {
                    let selected = selectedCards.includes(card)
                    return(<Card key={i} card={card} user="player" selectCard={selectCard} selected={selected}/>)
                }
          )}
    )
}

Card.js

const Card = (props) =>{
    const path = props.card.imagePath
    const [selected, setSelected] = useState(props.selected)

    useEffect(() => { setSelected(props.selected) }, [props.selected]);
    {/*My effort to make it work*/}

    const classname = (selected) ? "selectedcard" : ""
            return(
                <img onClick={() => props.selectCard(props.card)}  className={"card " + classname} alt = "card-image" src={images[path]}/>)
}

css

.selectedcard{
  margin-bottom: 40px;
  border-radius: 6px;
  box-shadow: 0px 0px 5px #fff !important;
}

Upvotes: 3

Views: 1572

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 282120

You shouldn't mutate the state while updating it, if you do so React sees in reference check that thee reference is same and assumes nothing has changed and doesn't trigger a re-render.

Follow the concept of immutability while updating react state. You can update it using Array.prototype.slice and spread syntax for deleting the item and using Array.prototype.concat for adding an item

const selectCard = (card) => {
    let newSelectedCards =[];
    if(newSelectedCards.includes(card) ) {
        const index = selectedCards.indexOf(card)
        newSelectedCards = [...selectedCards.slice(0, index), ...selectedCards.slice(index + 1)]
    } else {
        newSelectedCards = selectedCards.concat([card]);
    }
    setSelectCard(newSelectedCards)
    console.log('changed');
}

Upvotes: 3

Related Questions