首页 > 解决方案 > 是否可以在反应渲染函数之外访问状态变量?

问题描述

是否可以访问外部的状态变量render(),但内部反应自定义组件方法?

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

标签: reactjs

解决方案


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

根据React文档:

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

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

您甚至在调用 inside of 之前就尝试访问this.state.datainside of :getRainyDaysthis.setStatecomponentDidMount

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

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

但即使你调用this.getRainyDaysafter 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函数内部检查 state 中是否有正确的数据,然后再返回 some 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>
  );
}


推荐阅读