【问题标题】:"TypeError: Cannot read property 'name' of undefined" error“TypeError:无法读取未定义的属性‘名称’”错误
【发布时间】:2019-05-17 03:46:43
【问题描述】:

代码给了我这个“TypeError: Cannot read property 'name' of undefined”错误,尽管当我 console.log 它给了我对象

import React from "react";

class Random extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      breweries: []
    };
  }

  componentDidMount() {
    fetch("https://api.openbrewerydb.org/breweries")
      .then(response => response.json())
      .then((data) => {
        this.setState({
          breweries: data,
        })
      })
  }

  render() {
    const brewery = this.state.breweries[Math.floor(Math.random()*this.state.breweries.length)];
    return(
      <div>{brewery.name}</div>
    )
  }
}

export default Random;

【问题讨论】:

  • 当您在控制台记录 brewery.name 或只是 brewery 时?
  • 当我控制台只记录啤酒厂时
  • 你在你的控制台中得到这个:[ ] 然后[...your data] ?那么有两件事会记录到控制台吗?
  • 不,我只是拿到对象

标签: javascript reactjs


【解决方案1】:

直到异步请求完成,

this.state.breweries[Math.floor(Math.random()*this.state.breweries.length)] 

实际上会返回undefined,因为

Math.floor(Math.random()*this.state.breweries.length)

会返回0,因为this.state.breweries是一个空数组,所以会返回undefined

([][0] -> undefined)。


您必须确保brewery 尚未定义的可能性,例如:

<div>{brewery && brewery.name}</div>

【讨论】:

    【解决方案2】:

    有两种方法可以解决这个问题。

    方法一:UNSAFE_componentWillMount()

    您可以使用UNSAFE_componentWillMount() 代替componentDidMount()UNSAFE_componentWillMount() 在渲染组件之前执行,因此您将在内容渲染之前拥有处于状态的数据。这应该消除错误。

    方法二:验证状态为!Empty

    在您的render 方法中,您可以添加一个if 语句,说明breweriesnull,如果状态中没有其他啤酒厂等于this.state.breweries[Math.floor(Math.random()*this.state.breweries.length)]

    类似这样的:

    render() {
        const { breweries } = this.state;
        let brewery; 
        if (breweries.length === 0){
           brewery = null;
        } else {
          brewery= 
       this.state.breweries[Math.floor(Math.random()*this.state.breweries.length)];
        }
        return(
          <div>{brewery.name}</div>
        )
      }
    

    对于额外的保险,您可以结合使用这两种方法。如果这样做,您的组件将如下所示:

    import React from "react";
    
    class Random extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          breweries: []
        };
      }
    
      componentWillMount() {
        fetch("https://api.openbrewerydb.org/breweries")
          .then(response =>{ return response.json() })
          .then((data) => {
            this.setState({
              breweries: data,
            })
          })
      }
    
      render() {
        const { breweries } = this.state;
            let brewery; 
            if (breweries.length === 0){
               brewery = null;
            } else {
              brewery= 
           this.state.breweries[Math.floor(Math.random()*this.state.breweries.length)];
            }
        return(
          <div>{brewery.name}</div>
        )
      }
    }
    
    export default Random;
    

    应该这样做。希望这会有所帮助。

    编辑:警告

    我写了 willMount() 但它应该是 UNSAFE_componentWillMount()。 componentWillMount() 在版本 17 之后将无法工作。UNSAFE_componentWillMount() 在版本 17 之后将工作。对此感到抱歉。我忘了写不安全。

    【讨论】:

    • 这是一个有害的答案。我不建议任何人使用componentWillMount
    • componentWillMount 有问题。 Unsafe 将在版本 17 中运行。就个人而言,这不是我要走的路线。我会将这些数据作为道具传递或使用 redux。但是对于所有者的情况unsafe...willmount 很好。我还包括了另一种方法,以防所有者不习惯使用不安全的生命周期方法
    【解决方案3】:

    在尝试访问数组的索引之前,您应该确保已获取数据。当数组为空时,您的随机数学将评估为0,从而导致undefined

    import React from "react";
    
    class Random extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          breweries: null
        };
      }
    
      componentDidMount() {
        fetch("https://api.openbrewerydb.org/breweries")
          .then(response => response.json())
          .then((data) => {
            this.setState({
              breweries: data,
            })
          })
      }
    
      render() {
        if (this.state.breweries) {
          const brewery = this.state.breweries[Math.floor(Math.random()*this.state.breweries.length)];
          return(
            <div>{brewery.name}</div>
          )
        }
    
        return null
      }
    }
    
    export default Random;
    

    【讨论】:

    • 我不明白你在他的代码中做了什么改变还是为了参考?
    猜你喜欢
    • 2020-12-26
    • 2019-12-22
    • 2021-11-13
    • 2022-01-14
    • 2022-06-22
    • 2015-10-16
    • 2020-04-08
    • 2021-02-15
    • 1970-01-01
    相关资源
    最近更新 更多