I have tried finding the answer to this on StackOverflow and there are some related posts (eg React Child Component Not Updating After Parent State Change ) but I want to understand why this is not working...
I have a React application that will display a layout of character cards (that is, each card displays a different character). It uses a child component, CharacterBoard
, that lays out the CharacterCards
, which would be a grandchild component. I pass the characters
down from the App
to the CharacterBoard
as props, and CharacterBoard
in turn map
s these out the CharacterCard
s.
The problem is that I want the state of the character
to change when I click on one of them. Specifically, I want the revealed
field to change. However, even though the state change is reflected in the array of character
s in the App (that is, the revealed
field changes correctly), and the change is reflected in the array of character
s in CharacterBoard
, but not in CharacterCard
. In fact, my mapping does not seem to be called at all in CharacterBoard
when the props change.
Do I need to use something like getDerivedStateFromProps
in CharacterBoard
and set the state
of that component and then use the state
to map the values down to CharacterCard
? If so, why?
In short (tl;dr), can you pass props on down through the component chain and map them out along the way and still have all changes reflected automatically?
Thanks for any guidance.
If it helps, the render
method of my App is
render() {
const {state: {characters}} = this
return (
<div>
<header>
</header>
<main>
<CharacterBoard
onCardSelected={this.onCardSelected}
rowSize={logic.ROW_SIZE}
characters={characters}
cardSize={this.CARD_SIZE}/>
</main>
</div>
);
}
that of CharacterBoard
is
render() {
const {props: {characters, rowSize, cardSize,onCardSelected}} = this
const rowUnit = 12 / rowSize
const cardLayout = characters
.map((character, i) => (
<Col xs={6} sm={rowUnit} key={character.name}>
<CharacterCard
onCardSelected = {onCardSelected}
key={i + Math.random()}
character={character}
cardSize={cardSize}
/>
</Col>
)
)
return (
<div>
<Container>
<Row>
{cardLayout}
</Row>
</Container>
</div>
)
}
and finally CharacterCard
has this render
method
render() {
const {props: {character, cardSize}} = this
const {thumbnail, revealed} = character
const imgURL = `${thumbnail.path}/${cardSize}.${thumbnail.extension}`
const topCardClass = classNames('characterCard__card-back', {'characterCard__card-back--hidden': revealed})
console.log(revealed)
return < a href="/#" onClick={this.onCardSelected}>
<div className='characterCard__card'>
<div className={topCardClass}>
<img src="/images/card_back.png" alt=""/>
</div>
< div className='characterCard__card-front'>< img alt=''
src={imgURL}/>
</div>
</div>
</a>
}
Doh! A simple forgetting to setState
in App
. Knowing that it should work made me go back through the code one more time and see that, indeed, it was a stupid error on my part.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.