Reactjs TypeError:无法读取属性';火箭名称';未定义的,即使已定义

Reactjs TypeError:无法读取属性';火箭名称';未定义的,即使已定义,reactjs,api,react-router,Reactjs,Api,React Router,我正在使用SpaceXAPI构建一个个人项目。我使用React路由器动态加载组件,而不是刷新整个网站 这是我的LaunchDetails组件,我试图在其中输出一些数据: import React, { Component } from 'react' class LaunchDetail extends Component { state = { launch: [] } async componentDidMount () { try { const

我正在使用
SpaceX
API构建一个个人项目。我使用React路由器动态加载组件,而不是刷新整个网站

这是我的
LaunchDetails
组件,我试图在其中输出一些数据:

import React, { Component } from 'react'

class LaunchDetail extends Component {
  state = {
    launch: []
  }

  async componentDidMount () {
    try {
      const res = await fetch(`https://api.spacexdata.com/v3/launches/${this.props.match.params.flight_number}`)
      const data = await res.json()
      this.setState({
        launch: data,
        rocket: data.rocket
      })
    } catch (e) {
      console.log(e)
    }
  }

  render () {
    const { launch, rocket } = this.state

    console.log(rocket)

    return (
      <div>
        <div>
          <h1>{launch.mission_name}</h1>
          <p>SpaceX Flight Number: {launch.flight_number}</p>
          <p>Launched: {launch.launch_year}</p>
          <p>Rocket: {rocket.rocket_name}, {rocket.rocket_type}</p>
        </div>
      </div>
    )
  }
}

export default LaunchDetail
从中可以发现,react生命周期方法的顺序如下

componentWillMount-->渲染-->componentDidMount

您已使用初始化状态

状态={
发布:[]
}
因此,在第一次渲染时,
state.rocket
将是未定义的

要解决此问题,请初始化state.rocket或将
componentDidMount
更改为
componentWillMount
前者更受欢迎

注意
componentWillMount
在版本17中不推荐使用


在OP的编辑之后。您仍在将启动初始化为[]

在第一次渲染时,
launch.rocket
将被取消定义。因此,
launch.rocket.rocket\u name
将抛出一个错误

初始化
launch
以获得
rocket
字段。或者做类似的事情

(launch.rocket | |{}).rocket_name
,或者在访问
rocket_name

之前检查
rocket
是否已定义的其他方法,您可以发现react生命周期方法的顺序如下

componentWillMount-->渲染-->componentDidMount

您已使用初始化状态

状态={
发布:[]
}
因此,在第一次渲染时,
state.rocket
将是未定义的

要解决此问题,请初始化state.rocket或将
componentDidMount
更改为
componentWillMount
前者更受欢迎

注意
componentWillMount
在版本17中不推荐使用


在OP的编辑之后。您仍在将启动初始化为[]

在第一次渲染时,
launch.rocket
将被取消定义。因此,
launch.rocket.rocket\u name
将抛出一个错误

初始化
launch
以获得
rocket
字段。或者做类似的事情


(launch.rocket | |{}).rocket_name
,或者其他一些东西,在访问
rocket_name
之前检查
rocket
是否定义了
rocket_name

我很确定这不是由“3层深”属性引起的,但在渲染中更是如此:
rocket.rocket_name
。火箭最初不是在状态中定义的,因此
this.state.rocket
将是未定义的,它的access子属性将给出您正在获取的错误。您可以在
componentDidMount
中获取数据,但在第一次渲染后会调用该生命周期方法。因此,如果您应该有一个用于呈现的加载状态(用于获取数据时),并且最好是状态的默认值,请尝试在初始
状态中初始化
rocket
={launch:[]}
确定,因此我将
rocket
添加到状态,仍然是相同的错误。我现在已经删除了它,因此它现在引用了
launch.rocket.rocket\u name
,但错误仍然存在……我很确定这不是由“3级深度”属性引起的,但在渲染中更是如此:
rocket.rocket\u name
。火箭最初不是在状态中定义的,因此
this.state.rocket
将是未定义的,它的access子属性将给出您正在获取的错误。您可以在
componentDidMount
中获取数据,但在第一次渲染后会调用该生命周期方法。因此,如果您应该有一个用于呈现的加载状态(用于获取数据时),并且最好是状态的默认值,请尝试在初始
状态中初始化
rocket
={launch:[]}
确定,因此我将
rocket
添加到状态,仍然是相同的错误。我现在删除了它,因此它现在引用了
launch.rocket.rocket\u name
,但错误仍然存在……谢谢,这是我的代码:
launch:{rocket:[]}
希望您能看到这个,为什么我需要初始化
rocket
和该组件中的任何其他数据的状态,而不是调用所有数据的其他组件中的状态?我希望这是有意义的…您需要在该组件中初始化火箭状态的唯一原因是第一次渲染。正如你所假设的,总是会有一个
launch
对象,它有一个
rocket
道具,这个道具有
rocket\u name
字段。我个人不希望在这个组件中初始化rocket,而是在渲染中使用类似
(launch.rocket | |{})。rocket\u name
。这样,如果
rocket
未定义,访问
rocket\u name
不会抛出错误,只会不渲染任何内容。在
rocket
通过
componentDidMount
初始化后,它将呈现新的
rocket\u名称
谢谢,这是我的代码:
launch:{rocket:[]}
希望您能看到,为什么我需要初始化
rocket
和该组件中的任何其他数据的状态,而不是调用所有数据的其他组件中的状态?我希望这是有意义的…您需要在该组件中初始化火箭状态的唯一原因是第一次渲染。正如你所假设的,总是会有一个
launch
对象,它有一个
rocket
道具,这个道具有
rocket\u name
字段。我个人不希望在这个组件中初始化rocket,而是在渲染中使用类似
(launch.rocket | |{})。rocket\u name
。这样,如果
rocket
未定义,访问
rocket\u name
不会抛出错误,只会不渲染任何内容。通过
componentDidMount
初始化
rocket
后,它将呈现新的
rocket\u名称
import React, { Component } from 'react'

class LaunchDetail extends Component {
  state = {
    launch: []
  }

  async componentDidMount () {
    try {
      const res = await fetch(`https://api.spacexdata.com/v3/launches/${this.props.match.params.flight_number}`)
      const data = await res.json()
      this.setState({
        launch: data
      })
    } catch (e) {
      console.log(e)
    }
  }

  render () {
    const { launch } = this.state

    return (
      <div>
        <div>
          <h1>{launch.mission_name}</h1>
          <p>SpaceX Flight Number: {launch.flight_number}</p>
          <p>Launched: {launch.launch_year}</p>
          <p>Rocket: {launch.rocket.rocket_name}, {launch.rocket_type}</p>
        </div>
      </div>
    )
  }
}

export default LaunchDetail