简体   繁体   中英

Is it possible to access state variable outside of react render function?

Is it possible to access state variables outside of render() , but inside react custom component method?

  componentDidMount() {
    fetch(
      "some url here"
    )
      .then(res => res.json())
      .then(json => {
        const days = this.getRainyDays(json)

        this.setState({
          data: json,
          rainyDays: days
        });
      });
  }

 getRainyDays = (data) => {
    console.log('data inside getRainyDays', this.state.data) // this.state.data is undefined here
    console.log('data inside getRainyDays2', data) // data returns json fine
  }

  render() {
   console.log(this.state.data) // this.state.data is fine too.
    return (
      <div className="App">
        <header className="App-header">
          Calendar showing {this.state.rainyDays} rainy days
        </header>
        <Year weatherData={this.state.data} />
        <Weather />
      </div>
    );
  }

Yes, it is possible to access state inside of a component outside of the render method.

According to the React documentation:

setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall.

Since your initial state most likely doesn't have the data property set to some value, it comes back as undefined .

You're trying to access this.state.data inside of getRainyDays before you even call this.setState inside of componentDidMount :

componentDidMount() {
  fetch(...)
    .then(json => {
      const days = this.getRainyDays(json)
      this.setState(...)
    })
}

getRainyDays = (data) => {
  console.log('data inside getRainyDays', this.state.data)
}

But even if you called this.getRainyDays after this.setState , you cannot rely on this.setState updating your state immediately.

Again, from React documentation:

Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.

If you would like to double check, however, that your state updates correctly, you can pass a callback to setState that will get called after setState updates component's state, like so:

componentDidMount() {
  fetch(..)
    .then(res => res.json())
    .then(json => {
      const days = this.getRainyDays(json)

      this.setState({
        data: json,
        rainyDays: days
      }, () => {
        console.log('data in state', this.state.data)
      });
    });
}

One thing that I'd recommend, is to check, inside your render function, whether state has the right data in it before you return some JSX . You might run into issues where some components expects an array of items and it renders it immediately, but you're passing undefined to it and it crashes...

render() {
  // exit early and return `null` so that nothing gets rendered
  // if your API call hasn't finished
  if (!this.state.data || !this.state.rainyDays) {
    return null
  }
  return (
    <div className="App">
      <header className="App-header">
        Calendar showing {this.state.rainyDays} rainy days
      </header>
      <Year weatherData={this.state.data} />
      <Weather />
    </div>
  );
}

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