【问题标题】:Why does my state variable in ReactJS not render and why is it undefined?为什么我在 ReactJS 中的状态变量没有渲染,为什么它是未定义的?
【发布时间】:2020-11-02 13:13:48
【问题描述】:

React 和 JavaScript 的初学者,如果这是一个简单的修复,请见谅。

我正在从服务器获取数据并打算解析响应并将响应的元素存储在作为状态变量的数组中,因为我想使用状态的变化来相应地更新页面。

我遇到的问题是,在使用 fetch() 时,我能够从服务器检索数据,但显然我无法正确使用 setState() 将数据分配给变量。我读过 setState() 是异步的,因此您的状态变量可能不会立即更新,在这种情况下,我想知道我是否可以在状态变量(数组)更新时呈现应用程序。

下面是我的代码:

import React, { Component } from 'react';
import './App.css';

class App extends Component{
  constructor(props)  {
    super(props);
    this.state = { 
      apiResponse: []
    }; 
    this.getData = this.getData.bind(this);
  }
  componentDidMount() {
    this.getData();
  }

  getData = () => {
    fetch('http://localhost:5000')
      .then(results => results.json())
      .then(console.log)
      .then(results => this.setState({apiResponse: results}, () => {
        console.log('data in state', this.state.apiResponse)
      }))
      .catch(err => console.error(err));
  }
  render()  {
    return (
      <div className="App">
        <h1>Display</h1>
        <h1>{this.state.apiResponse}</h1>
        <h1>Does this work?</h1>
      </div>
    );
  }
}

export default App;

我在 fetch 之后运行的第一个 console.log 返回了适当的 JSON 对象,但是之后的下一个 console.log 返回一个未定义的,{this.state.apiResponse} 不呈现任何内容。

【问题讨论】:

  • 删除.then(console.log)
  • 你能显示你从服务器得到什么吗?
  • @panditmonium 以及你想在 UI 中显示什么?
  • @panditmonium 对于您需要调用的每个阵列map{this.state.apiResponse &amp;&amp; this.state.apiResponse.map(apiRep =&gt; &lt;div&gt;{apiRep.recordsets.map(recordSet =&gt; &lt;span&gt;{recordSet.FactoryName}&lt;/span&gt;)}&lt;/div&gt;)}。现在无法检查所有 {} () 是否都正常
  • 我想要它,以便我可以显示属于记录集 [0] 索引的所有元素。从那里,我将解析 JSON 以检索一些变量(一个是“E10StateName”)

标签: javascript reactjs fetch state render


【解决方案1】:

您正在使用 then 方法处理 json 对象,但随后您没有返回任何内容以便让下一个 then 作为输入。

如果您删除此行

.then(console.log)

那么它应该可以工作。

【讨论】:

  • 您好 apostolos,感谢您的回复!我已经尝试过你的解决方案,我想知道这是否意味着我走在正确的道路上......我收到一条错误消息,指出“对象作为 React 子项无效(找到:带键的对象)。如果你的意思是渲染一个孩子的集合,用一个数组来代替。”你有什么建议我可以解决这个问题吗?再次感谢您的回复!
  • 如果是数组,可以使用map函数。
  • @panditmonium 您需要相应地处理您的this.state.apiResponse。如果不是字符串、数字,则不能只用{this.state.apiResponse} 显示。检查map方法
  • 例如{this.state.apiResponse.map(obj =&gt; &lt;span&gt;{obj.SOME_PROPERTY}&lt;/span&gt;)}
  • 所以我尝试了以下... {apiResponse.map(apiRep => {apiRep.recordsets})} 这导致未定义“apiResponse”...有什么建议吗?
【解决方案2】:

问题是当你作为回调传递给 then consol.log 函数并且在你继续 then 链接并期望能够访问结果之后,你应该做的是直接调用then 链,您在调用 console.log 之前设置 state,然后在回调中返回 results,如下所示

fetch('http://localhost:5000')
  .then(results => results.json()) 
  .then(results => {
      this.setState({apiResponse: results}, () => {
          console.log('data in state', this.state.apiResponse)
      });
      return result;
   })
   .then(console.log);

或者只是用这样的普通函数替换它

fetch('http://localhost:5000')
  .then(results => results.json())
  .then((results) => {
      console.log(results);
      return results;
  })
  .then(results => {
      this.setState({apiResponse: results}, () => {
          console.log('data in state', this.state.apiResponse)
      });
      return result;
   });

【讨论】:

    【解决方案3】:

    每当您使用 .then() 解析 Promise 时,您都希望将解析传递给下一个回调。 .then(console.log) 打破了这一点。您在下一次回调中没有结果。 阅读更多关于 here 的信息。

    【讨论】:

      【解决方案4】:

      这是你的Chaining的问题,这是一个答案:

      then 方法返回一个允许方法链接的 Promise。

      如果函数作为处理程序传递给 then 返回一个 Promise,一个 等价的 Promise 将暴露给随后的 then 在 方法链。 -MDN

      ...
            .then(console.log) // here you're not exposing any response
      ...
        }
      

      补救措施可能是:

      ...
      getData = () => {
          fetch('http://localhost:5000')
            .then(results => {console.log(results); return results.json()})
            .then(results => this.setState({apiResponse: results}, () => {
              console.log('data in state', this.state.apiResponse)
            }))
            .catch(err => console.error(err));
        }
      ...
      
      

      【讨论】:

        【解决方案5】:
            import React, { Component } from 'react';
            import './App.css';
            
            class App extends Component{
              constructor(props)  {
                super(props);
                this.state = { 
                  apiResponse: []
                }; 
                this.getData = this.getData.bind(this);
              }
              componentDidMount() {
                this.getData();
              }
            
              getData = () => {
                fetch('http://localhost:5000')
                  .then(results => results.json())
                  .then(console.log)
                  .then(results => this.setState({apiResponse: results}))
                  .catch(err => console.error(err));
              }
              render()  {
                return (
                  <div className="App">
                    <h1>Display</h1>
                    <h1>{this.state.apiResponse && 
                 this.state.apiResponse.recordSets.map((singleRecord, index)=>           
          singleRecord.map(singleElement => <span> 
                      {singleElement.FactoryName}</span>))}</h1>
                        <h1>Does this work?</h1>
                      </div>
                    );
              }
            }
            
            export default App;
        

        【讨论】:

        • 这是我得到的错误... 预期一个赋值或函数调用,而是看到一个表达式 no-unused-expression
        • @panditmonium,我已经更新了我的答案,并且也进行了测试。它将解决问题。
        • 嘿,我尝试了您的代码并进行了小修复(必须将 this.state.apiResponse && ... 切换到 this.state.apiResponse.recordsets && ...),它成功了!感谢您的帮助和支持!!
        • 很高兴它有帮助。
        猜你喜欢
        • 2014-08-20
        • 2021-09-13
        • 2015-04-23
        • 2016-12-30
        • 2017-04-07
        • 1970-01-01
        • 2021-11-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多