Farah10
Farah10

Reputation: 91

Updated state not rendering in child component

I am trying to pull a picture from NASA's API to get their astronomy picture of the day. When I update the state in my API call and console.log this.state.picture, I can see that picture has been set to the data object. But when I try to log picture in render, it logs an empty array. I used a similar approach in previous assignments and never had this issue, so I really can't figure out what I'm doing wrong. I'm new to React, so sorry if the answer is really obvious.

Parent component:

class App extends Component {
  state = {
    picture: [],
    asteroids: [],
  }

  render() {
    return (
      <div className="App">
        <Route exact path="/" component={Homepage}/>

        <Route path="/apod" render={() => 
          <APOD picture={this.state.picture}/>}/>

        <Route path="/asteroids" render={() =>
          <Asteroids asteroids={this.state.asteroids} />} />
      </div>
    );
  }
}

export default App;

Child component:

class Apod extends React.Component{
  getApodPicture = e => {
    e.preventDefault();

    let url = `https://api.nasa.gov/planetary/apod?api_key=v1sEi9chxFYzrf1uXei0J1GvXaemhnQXiDjEcnK2`;
    fetch(url)
      .then(res => {
        if (!res.ok){
          throw new Error (res.status)
        }
        return res.json();
      })
      .then(data => {
        this.setState({picture: data})
        console.log(this.state.picture) // logs the data object from NASA
      })
      .catch(err => console.log(err))
  }

  render(){
    console.log(this.props.picture) // logs []
    // console.log(this.state.picture) // returns "Cannot read property 'picture' of null"
  return(
    <div>
      <h1>Astronomy picture of the day!</h1>
      <Link to="/">Back to homepage</Link>

      <section>
        <button onClick={e => this.getApodPicture(e)}>Click to see picture</button>
      </section>
    </div>
  )
  } 
}

export default Apod;

Upvotes: 3

Views: 81

Answers (1)

Beaulne
Beaulne

Reputation: 549

This.setState will set the state of the component, not the parent component.

you will need a changeHandler to get the desired result.

something along the lines of


class App extends Component {
  state = {
    picture: '',
    asteroids: [],
  }

  pictureChangeHandler = value => {
    this.setState(value);
  }

  render() {
    return (
      <div className="App">
        <Route exact path="/" component={Homepage}/>

        <Route path="/apod" render={() => 
          <APOD pictureChangeHandler={this.pictureChangeHandler} 
 picture={this.state.picture}/>}/>

        <Route path="/asteroids" render={() =>
          <Asteroids asteroids={this.state.asteroids} />} />
      </div>
    );
  }
}

export default App;

class Apod extends React.Component{
  getApodPicture = e => {
    e.preventDefault();

    let url = `https://api.nasa.gov/planetary/apod?api_key=v1sEi9chxFYzrf1uXei0J1GvXaemhnQXiDjEcnK2`;
    fetch(url)
      .then(res => {
        if (!res.ok){
          throw new Error (res.status)
        }
        return res.json();
      })
      .then(data => {
        this.props.pictureChangeHandler(data)

      })
      .catch(err => console.log(err))
  }

  render(){
    console.log(this.props.picture) // logs []
    // console.log(this.state.picture) // returns "Cannot read property 'picture' of null"
  return(
    <div>
      <h1>Astronomy picture of the day!</h1>
      <Link to="/">Back to homepage</Link>

      <section>
        <button onClick={e => this.getApodPicture(e)}>Click to see picture</button>
      </section>
    </div>
  )
  } 
}


Upvotes: 1

Related Questions