简体   繁体   中英

Why does my React grandchild component not update after receiving a change in props from its parent? Or: do I need to use state?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM