【问题标题】:Attempt to render state value from ajax call in componentDidMount failing (React)尝试从 componentDidMount 中的 ajax 调用呈现状态值失败(React)
【发布时间】:2017-02-18 16:15:36
【问题描述】:

我在 React 中使用 Axios 进行了 AJAX 调用,我对如何处理响应有点困惑。

这是我的代码:

componentDidMount() {
   axios.get('https://jsonplaceholder.typicode.com/users')
      .then( res => {
         const users = res.data
         this.setState({ users });
      });
}

render() {
   console.log(this.state.users)  
   return (
   <div>
      {this.state.users.map( user => <p>{user.name}</p>)}
   </div>
   )
}

当我对结果进行 console.log 时,会返回两个值:

  1. [] - 分配给初始状态的空数组
  2. 来自 API 的预期数组。

这大概可以解释为状态值在初始化时返回一次,然后再次使用 componentDidMount。

我的问题在于如何访问 this.state.users 值。显然,任何时候我访问它时,我都想要从 AJAX 响应返回的值,但是如果我尝试从数组中的第一个对象呈现 name 属性...

{this.state.users[0].name}

...它尝试访问[],因此没有返回任何内容。

但是,如果我尝试遍历数组元素...

{users.map( user =&gt; &lt;p&gt;user.name&lt;/p&gt; )}

...它按预期返回值。

我不知道为什么它适用于第二个示例而不是第一个示例。当然,如果第一个尝试从初始状态值(空数组)中提取数据,那么当 mappingthis.state.users 时,它也将尝试通过空数组进行映射并且不返回任何内容,或者一个错误。

我显然没有完全理解这里的 React 渲染过程以及 componentDidMount 在组件生命周期中是如何工作的。尝试将响应值直接分配给状态我错了吗?

如果有人可以帮助解决这个问题,我们将不胜感激。

【问题讨论】:

    标签: javascript arrays ajax reactjs state


    【解决方案1】:

    当您最初在this.state.users 上使用map() 时,它将在一个空数组上执行此操作(不会渲染任何内容)。一旦响应到达,this.setState({ users }) 被调用,render() 将再次运行。这次用户数组不再为空,对数组中的每个用户都执行map()操作。

    但是,当您最初在空数组上使用 {this.state.users[0].name} 时,您会尝试访问尚不存在的对象的 name 属性 — 这将导致错误。为防止该错误,您可以在访问对象的属性之前进行检查:

    {this.state.users.length > 0 && this.state.users[0].name}
    

    现在它的行为方式与第一个示例相同。 IE。第一个render() 实际上不会做任何事情,因为this.state.users.length = 0。但是一旦有新用户调用this.setState()render() 就会再次运行,这一次this.state.users[0].name 可用。

    【讨论】:

    • 谢谢,这有帮助。以某种方式访问​​数据仍然感觉有点“hacky”的方式,但如果它有效,我猜它有效:)
    • 我实际上并不认为它是 hacky,但你可以通过多种方式做到这一点。一种方法是像这样拉出用户:firstUser = this.state.users[0] || {}。那么{firstUser.name} 至少不会给你报错。不过就个人而言,我更喜欢第一种选择。
    • 好的,这是一个不错的选择,谢谢。我想我可能只是不习惯 React 的做事方式——组件渲染的不同生命周期阶段的优点可能抵消了必须提供条件语句来渲染状态值的任何小缺点。
    • 尝试访问this.state.users[0].name,当数组为空时,无论React如何都会导致错误。这实际上只是一个JS错误。我认为混淆可能更多是关于 ajax 是异步的。如果您不希望组件在收到数据之前呈现,您可以返回 null、加载微调器等,直到数据存在为止。
    【解决方案2】:

    构造函数还有另一种方式。只需将您的状态与空数组用户添加为-

       constructor(props) {
          super(props);
          this.state = {
             users: []
          };
       }
    

    此组件首先使用空的 users 数组呈现。当您触发状态更新时,组件会使用新数组重新渲染。

    【讨论】:

    • 抱歉,我的代码 sn-p 没有包含它 - 这就是我渲染空数组的方式。
    猜你喜欢
    • 2018-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 2019-08-20
    • 2019-10-10
    • 2016-03-01
    相关资源
    最近更新 更多