TypeError:无法读取null的属性状态

时间:2018-11-29 02:42:57

标签: javascript reactjs

我无法使数据恢复状态并在其上应用map函数。我不断得到

  

TypeError:无法读取null的属性“ financials”。

axios获取以下对象,{符号:“ AAPL”,财务:Array(4)},这就是为什么我使用this.state.financials.financials

class Fundamentals extends Component {
  state = {
    financials: null,
    headers: null
  };

  async componentDidMount() {
    console.log("componentDidMOunt");
    await axios
      .get("https://api.iextrading.com/1.0/stock/aapl/financials?period=annual")
      .then(res => {
        const financials = res.data;
        this.setState({ financials });
        console.log(financials);
      });

    console.log("componentDidMount finished setting the data for the table");
  }

  render() {
    // const headers = this.getHeaders1();
    return (
      <GridContainer>
        <GridItem xs={12} sm={12} md={12}>
          <Card>
            {this.state.financials.financials.map(items => items)} <-- i want to get the data out of state and later put it into a table. 
          </Card>
        </GridItem>
      </GridContainer>
    );
  }
}

3 个答案:

答案 0 :(得分:2)

第一次渲染组件时,this.state.financialsnull,因为您正在使用null对其进行初始化:

state = {
  financials: null,
  headers: null
};

这就是为什么您遇到该错误的原因。这是一个复制错误的简单示例:

var state = {
  financials: null,
};

state.financials.financials.map(() => {});

您需要检查渲染方法是否设置了该值,如果未设置,则什么也不做:

render() {
  // const headers = this.getHeaders1();
  if (!this.state.financials) {
    return null; // or some message that the data is loading
  }

  return (
    <GridContainer>
      <GridItem xs={12} sm={12} md={12}>
        <Card>
          {this.state.financials.financials.map(items => items)} <-- i want to get the data out of state and later put it into a table. 
        </Card>
      </GridItem>
    </GridContainer>
  );
}

或者,您也可以使用{financials: []}对其进行初始化:

state = {
  financials: {financials: []},
  headers: null
};

然后,您在render中的现有代码应“起作用”(见下文)。


但是,仅此一项可能无法使您的组件正常工作。您实际上还需要将this.state.financials.financials中的条目转换为React可以呈现的内容。这是一个提取日期的示例:

this.state.financials.financials.map(item => item.reportDate)

根据您的需要进行调整。

答案 1 :(得分:1)

在实际呈现数据之前添加检查。

class Fundamentals extends Component {
  state = {
    financials: null,
    headers: null
  };

  async componentDidMount() {
    console.log("componentDidMOunt");
    await axios
      .get("https://api.iextrading.com/1.0/stock/aapl/financials?period=annual")
      .then(res => {
        const financials = res.data;
        this.setState({ financials });
        console.log(financials);
      });

    console.log("componentDidMount finished setting the data for the table");
  }

  render() {
    const { financials: { financials} } = this.state;

    if(!financials || (financials && !financials.length) {
      return (
        <LoaderComponent />
      )
    }

    return (
      <GridContainer>
        <GridItem xs={12} sm={12} md={12}>
          <Card>
            {financials.map(items => items)} <-- i want to get the data out of state and later put it into a table. 
          </Card>
        </GridItem>
      </GridContainer>
    );
  }
}

答案 2 :(得分:1)

该错误是因为React在API调用完成之前尝试渲染,在这种情况下this.state.financials仍为其分配了初始值null

按如下所述更改金融的默认值

state = {
    financials: { financials: [] },
    headers: null
};

所以最终代码看起来像

class Fundamentals extends Component {
  state = {
    financials: { financials: [] },
    headers: null
  };

  async componentDidMount() {
    console.log("componentDidMOunt");
    await axios
      .get("https://api.iextrading.com/1.0/stock/aapl/financials?period=annual")
      .then(res => {
         const financials = res.data;
         this.setState({ financials });
         console.log(financials);
      });

      console.log("componentDidMount finished setting the data for the table");
   }

   render() {
     // const headers = this.getHeaders1();
     return (
       <GridContainer>
         <GridItem xs={12} sm={12} md={12}>
           <Card>
             {this.state.financials.financials.map(items => items)} <-- i want to get the data out of state and later put it into a table. 
           </Card>
         </GridItem>
       </GridContainer>
     );
  }
}