【问题标题】:Getting React errors when traversing an in-scope JSON object via Dot Notation [duplicate]通过点表示法遍历范围内 JSON 对象时出现 React 错误 [重复]
【发布时间】:2019-03-24 03:58:48
【问题描述】:
render() {
    return (
        <p>{this.state.recipes[0].title}</p> // This is what I believe should work - Ref Pic #1
        // <p>{this.state.recipes[0]}</p>    // This was trying random stuff to see what happens - Ref Pic #2
        // <p>{this.state.recipes.title}</p> // This was me trying crazy nonsense - Ref Pic #3
    )
}

我正在尝试遍历一些 JSON 并得到一些非常不稳定的响应。如果有人想亲自查看 JSON,请访问 this link

当第一个 p 标签运行时,我得到以下响应: This is my first question, so I can't embed images, I'm sorry.

由于不确定为什么它说 recipes[0] 未定义,我再次运行它,第二个 p 标签单独未注释,我得到以下回复:Still the same question, still can't embed, sorry again.

这个响应真的让我措手不及,因为它引用的键(nid、title 等)是我知道的对象中的键。 “标题”是我想要的。

最后,我只尝试了第三个 p 标签,应用程序实际编译到该标签没有错误,但 p 标签是空的。 Here's what I have in React Devtools, but I still can't embed.

查看,它清楚地表明状态具有我想要的状态,并且图像二显示recipes[0] 具有我第一次尝试调用的键。我搜索和谷歌搜索,甚至把我自己的亲人当作橡皮鸭,但无济于事。

我做错了什么?

【问题讨论】:

  • 您是在异步获取 JSON 吗?

标签: javascript json reactjs


【解决方案1】:

第一个 p 标签中的错误告诉你到底发生了什么。访问“未定义”的属性会破坏 javascript/react。

您的状态中可能没有预期的数据,要验证我在说什么,只需在您的渲染中通过 console.log(this.state) 进行调试:

render() {
  console.log(this.state); // probably has this.state.recipes empty array at first render
  ...

这可能是因为您的状态是由来自 api 的异步调用填充的。 Render 将在您来自 api 的异步请求解析之前首先被调用(这意味着不幸的是,您的状态还没有 ..recipes[0] 数据)

我猜你的 componentDidMount 中有这个:

componentDidMount() {
  ThirdParty.fetchRecipes().then(data => {
     this.setState({ recipes: data.recipes }); // after setState react calls render again. This time your p tag should work.
  })
  ...

如果您有较新的 react 版本,我建议您使用 可选链接,因为您感兴趣的属性嵌套很深:How to handle calling functions on data that may be undefined?

&lt;p&gt;{this.state?.recipes?.[0]?.title}&lt;/p&gt;

另一种有效的方法,但太罗嗦了:

const title =
  this.state &&
  this.state.recipes &&
  this.state.recipes.length &&
  this.state.recipes[0].title
    ? this.state.recipes[0].title
    : "";

render() {return (<p>{title}</p>)}

【讨论】:

  • 我的 componentDidMount 与您的示例几乎相同。它包括我的提取,然后以以下内容结束:.then((data) =&gt; { console.log(data) this.setState({ recipes: data }) }) 控制台记录的数据是正确的,状态更改应该触发重新渲染,但它仍然显示未定义。
  • 好了,继续下一步:在render中记录这次的状态,看我上面的建议。并让我知道实际数据,下一次重新渲染后它不可能仍然未定义
【解决方案2】:

我相信您正在异步获取 JSON。在这种情况下,您应该考虑初始配方状态为空数组的边界情况。

  1. 当你运行第一个p标签时,由于JSON是异步获取的,最初this.state.recipes没有被定义,因此你得到了错误。

  2. 1234563再次,这次this.state.recipes[0] 是一个对象,因此它不能算作有效的反应组件,因此会出现错误。
  3. 使用第三个p 标签,正如您自己提到的,this.state.recipes.title 将成功编译,没有错误,但值将未定义。

您只需要检查初始状态为空的边缘情况。

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

        render() {
             return (
                 <p>
                  {this.state.recipes.length > 0 ? {this.state.recipes[0].title} : ''}       
                </p> 
             )
         }

【讨论】:

    【解决方案3】:

    你可以做这样的事情来处理有数据和没有数据时的状态

    constructor(props) {
          super(props);
    
          this.state = {
            recipes: []
          };
        }
    
    
     render() {
                 return (
                     <p>
                      {this.state.recipes && this.state.recipes.length ? {this.state.recipes[0].title} : {this.state.recipes}}       
                    </p> 
                 )
             }
    

    【讨论】:

    • 当 recipes 是一个空数组(这是真的)时,这仍然会中断:this.state.recipes ? {this.state.recipes[0].title} : {this.state.recipes}
    • 已更新修复
    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 2018-11-24
    • 2013-08-25
    • 2020-12-10
    • 1970-01-01
    • 2022-11-10
    • 2017-07-10
    • 2020-09-07
    相关资源
    最近更新 更多