【问题标题】:Object property returning undefined after mounting component and setState安装组件和 setState 后返回未定义的对象属性
【发布时间】:2017-08-10 02:20:36
【问题描述】:

我正在使用来自 axios.get 的回调来设置 React 组件的状态。响应的 data 属性包含我用来设置状态的对象数组。

当我将 state 属性记录到控制台时,没有任何问题,我可以看到对象数组。但是,如果我尝试单独记录其中一个对象,则会收到错误消息:

在 ResponsiveTable.render 中无法读取 null 的属性“0”

下面是我的组件的代码:

class ResponsiveTable extends React.Component {

    constructor (props) {
        super(props)
        this.state = {
            returnedQuery: null
        };
    }

    componentDidMount() {
        axios.get('/api/latestLeads')
          .then((response) => {
              this.setState({
                  returnedQuery: response.data
              });
          })
          .catch(function (error) {
              console.log(error);
          });
    }

    render() {

        console.log(this.state.returnedQuery[0]);

        return (
            <div>
                <h1>test</h1>
            </div>
        );
    }
}

【问题讨论】:

  • rendercomponentDidMount 之前被调用

标签: reactjs


【解决方案1】:

确保在第一次渲染时返回的查询为空,因此您会收到此错误。

如果你想使用this.state.returnedQuery[0] 检查它是否存在并且它的长度> 0:

render() {
        if (this.state.returnedQuery && this.state.returnedQuery.lenth > 0){ 
                return (
                    <div>
                        {this.state.returnedQuery.map(...)}
                    </div>
                );
        } else {
            return <div>loading data...</div>
        }
    }

【讨论】:

  • 我应该更好地解释这个场景,计划是使用 .map 方法遍历返回的数组以呈现行内填充的表格单元格。所以我需要数组属性中的对象在渲染函数中可用
  • @NiallFaucher,看,首先渲染将工作else,因为来自构造函数的this.state.returnedQuery === null。然后,在 axios 查询之后,setState 将第二次触发 redner,但 this.state.returnedQuery === [{},{},{}] 将运行 if 语句的第一部分。
【解决方案2】:

你可以试试这个:

class ResponsiveTable extends React.Component {

    constructor (props) {
        super(props)
        this.state = {
            returnedQuery: null
        };
        this.getData();
    }

    getData = () => {
         axios.get('/api/latestLeads')
          .then((response) => {
              this.setState({
                  returnedQuery: response.data
              }, () => {console.log(this.state.returnedQuery);}); //What does this console.log() say?
          })
          .catch(function (error) {
              console.log(error);
          });
    }

    render() {

        console.log(this.state.returnedQuery[0]);

        return (
            <div>
                <h1>test</h1>
            </div>
        );
    }
}

【讨论】:

  • 针对您的问题,console.log();返回数组但使用 console.log(this.state.returnedQuery[0]);在渲染函数中仍然会导致错误我认为这是 Andrew point 关于第一次渲染的解释。我需要找到一种方法让第一次渲染等到 response.data 准备好
  • 但是为什么呢?在你改变状态的那一刻,react 会重新渲染。你想用returnedQuery[0] 做什么?我不会反对做出反应并尝试强迫render() 等待或某事。像这样
【解决方案3】:

我找到了和上面 Andrew 非常相似的解决方案,我使用组件的内部状态来确定 axios.get 方法是否已经返回。下面是工作代码,我现在可以访问返回数组中的元素及其属性。

class ResponsiveTable extends React.Component {

    constructor (props) {
        super(props)
        this.state = {
            returnedQuery: null
        };
    }

    componentDidMount() {

        const self = this;

        // let returnedQuery;
        axios.get('/api/latestLeads')
          .then((response) => {
              self.setState({
                  returnedQuery: response.data
              });
              console.log(response.data);
          })
          .catch(function (error) {
              console.log(error);
          });
    }

    render() {
        return (
          <div>
              <h1>{'This will always render'}</h1>
              { this.state && this.state.returnedQuery &&
              <div>{this.state.returnedQuery[0].email}</div>
              }
          </div>
        )
    }
}

【讨论】:

  • 您不需要这样做:const self = this; 这是 1997 年的代码。而是使用箭头函数将函数绑定到您的组件:myFunction = () =&gt; {...} 您现在可以在正确范围内访问组件内的“this”。 componentDidiMount 之类的反应函数通常已经绑定。尝试这样做:this.setState(...)
猜你喜欢
  • 2019-06-17
  • 1970-01-01
  • 2021-11-10
  • 2015-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-22
相关资源
最近更新 更多