是否可以在react render函数之外访问状态变量?

时间:2019-08-09 22:32:19

标签: reactjs

是否可以访问render()之外的状态变量,但是可以在React自定义组件方法中访问状态变量?

  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>
    );
  }

1 个答案:

答案 0 :(得分:1)

是的,可以在render方法之外的组件内部访问状态。

根据React文档:

  

setState()并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用this.state之后立即阅读setState()可能是一个陷阱。

由于您的初始状态很可能没有将data属性设置为某个值,因此其返回为undefined

您试图在this.state.data内部访问getRainyDays之前访问this.setState内部的componentDidMount

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

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

但是,即使您在this.getRainyDays之后致电this.setState,也不能依靠this.setState立即更新状态。

再次根据React文档:

  

setState()视为请求而不是立即命令来更新组件。为了获得更好的感知性能,React可能会延迟它,然后在一次通过中更新几个组件。 React不能保证状态更改会立即应用。

但是,如果您要仔细检查状态是否正确更新,则可以将回调传递给setState,该回调将在setState更新组件的状态后被调用,如下所示:

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)
      });
    });
}

我建议的一件事是,在返回render之前,先检查JSX函数内部状态是否包含正确的数据。您可能会遇到一些问题,其中某些组件需要一个项目数组并立即呈现它,但是您向其中传递了undefined并崩溃了...

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>
  );
}