【问题标题】:React - Array in state is defined, but Array[index] is undefinedReact - 状态中的数组已定义,但 Array[index] 未定义
【发布时间】:2021-01-28 09:39:55
【问题描述】:

我正在编写一个反应应用程序来从后端数据库中获取词汇表,然后将其显示给用户,以及有关每个特定单词的一些信息。我的问题是,由于数组的索引未定义,我无法在 render() 中显示单词,但是根据 chrome devtools,数组已完全定义。

这是我的代码:

import React from 'react';
import "./Vocab.css"

 class Vocab extends React.Component {
   //HEADER HEADER HEADER

   state = {
     vocabulary: null,
     var2: null
   };

   componentDidMount(){
     //Initializing Routine Here
     this.getVocab()
   }

   getVocab = () => {
     var newVocab = [];
     if(this.state.vocabulary == null){
       newVocab = newVocab;
     }
     else{
       newVocab = [this.state.vocabulary];
     }
     this.props.HandleFetch("GET", this.props.backLink + "vocab")
      .then(r => JSON.parse(r))
      .then(data => newVocab.push(data[0]))
      .then(this.setState({vocabulary:newVocab}))
   }

   //In render() variable display and the if/else statements are used exclusively for testing purposes
   render() {
     var display = "X";
     if(this.state.vocabulary == null){
       display = "Y";
     }
     else{
       console.log(this.state.vocabulary); //Outputs the array 
       console.log(this.state.vocabulary[0]) //Outputs "undefined"
       display = "Z";
     }
     return (
       <>
       <h1>Test</h1>
       {display}
       </>
     );
   }
 }
 export default Vocab;

console.log(this.state.vocabulary)的输出:

0:
Definition: "TestDef"
IPA: "TestIPA"
IsCard: true
Language: "TestLang"
LastStudyDate: "2021-01-27"
Mnem: ""
PoS: "TestPO"
Source: "TestDict"
SourceLearned: "TestSource"
Word: "Test"

this.state.vocabulary[0]的输出:

undefined

此外,根据 chrome devtools 并通过在控制台中键入 $r.state.vocabulary[0] 我在数组的索引处获得字典,这是我需要的:

{Word: "Test", Mnem: "", LastStudyDate: "2021-01-27", SourceLearned: "TestSource", IsCard: true, …}

在控制台中,数组是完全可导航的,但网页本身不会呈现它。知道我可能做错了什么吗?

更新 我能够添加一个按钮,onClick 转到打印出词汇和词汇[0] 的功能。这确实有效,但 render() 函数和 componentDidUpdate() 函数仍然无法访问词汇表[0]。我在 react 文档中没有看到任何关于 setState() 完成或在 componentDidUpdate() 之后发生的任何函数的内容。

此外,在早期的一些测试中,我尝试 console.log newVocab[0] 在将其分配给 .then 字符串中的状态之前。这有效,但仅在我所有其他控制台调用之后才在控制台中输出,这表明它发生在组件重新渲染和更新周期之后,即使我在调用 setState() 之前调用它。

我目前的测试代码:

import "./Vocab.css"

 class Vocab extends React.Component {
   //HEADER HEADER HEADER

   state = {
     vocabulary: null,
     var2: null
   };

   componentDidMount(){
     //Initializing Routine Here
     this.getVocab()
   }

   componentDidUpdate(){
     console.log("Vocab update");
     console.log(this.state.vocabulary);
     console.log("Vocab[0] update");
     console.log(this.state.vocabulary[0]);
     ///Outputs the vocabulary array, and then 'undefined'
   }

   getVocab = () => {
     var newVocab = [];
     if(this.state.vocabulary == null){
       newVocab = newVocab;
     }
     else{
       newVocab = this.state.vocabulary;
     }
     this.props.HandleFetch("GET", this.props.backLink + "vocab")
      .then(r => JSON.parse(r))
      .then(data => newVocab.push(data[0]))
      .then(this.setState({vocabulary:newVocab}))
   }

   logVocab = () => {
     console.log("Vocab");
     console.log(this.state.vocabulary);
     console.log("Vocab[0]");
     console.log(this.state.vocabulary[0]);
     ///Outputs the vocabulary array, and then the dictionary at index[0].
   }

   render() {
     var display = "X";
     if(this.state.vocabulary == null){
       display = "Y";
       console.log("Y");
     }
     else{
       console.log("Vocab Z");
       console.log(this.state.vocabulary);
       console.log("Vocab[0] Z");
       console.log(this.state.vocabulary[0]);
       display = "Z";
       ///Outputs the vocabulary array, and then 'undefined'
     }
     return (
       <>
       <h1>Test</h1>
       {this.state.vocabulary ? this.state.vocabulary[0] : ""}
       <button onClick = {this.logVocab}> CLICK </button>
       </>
     );
   }
 }
 export default Vocab;

【问题讨论】:

  • 你能从this.props.HandleFetch("GET", this.props.backLink + "vocab") .then(r =&gt; JSON.parse(r))登录你的r
  • @antoineso 确定!这是[{"Word": "Test", "Mnem": "", "LastStudyDate": "2021-01-27", "SourceLearned": "TestSource", "IsCard": true, "IPA": "TestIPA", "PoS": "TestPO", "Definition": "TestDef", "Source": "TestDict", "Language": "TestLang"}]

标签: javascript arrays reactjs


【解决方案1】:

问题是当您尝试注销vocabulary[0] 时,state.vocabulary 仍然为空。由于this.props.HandleFetch是一个异步操作,所以需要等到this.state.vocabulary被设置,像这样:

render() {
  const { vocabulary } = this.state;
  if (!vocabulary) {
    // render nothing if vocabulary is null
    return null;
  }

  // This will log out the first element of vocabulary instead of undefined
  console.log(this.state.vocabulary[0]);

  return (
    ...
  );
}

UPD:你在getVocab方法中也有错误的语法:

      .then(this.setState({vocabulary:newVocab}))

它的作用是立即将vocabulary 分配给newVocab 变量,该变量在执行时是一个空数组。然后,当this.props.HandleFetch 得到满足时,newVocab 将填充响应数据。

你可以像下面这样解决这个问题:

   this.props.HandleFetch("GET", this.props.backLink + "vocab")
      .then(r => JSON.parse(r))
      .then(data => this.setState({ vocabulary: data[0] }))

【讨论】:

  • 我想我不明白的是,当词汇本身返回一个数组时,词汇[0] 怎么可能为空?在我的 render() 函数中,我在 if/else 树中进行 nullcheck,它输出数组本身很好,但不是索引。
  • 更新了我的答案,请查看
  • 我检查了,我觉得这样做会限制我更新或添加到词汇表的能力。而不是现在我在词汇表中的内容并制作副本(就像我目前所做的那样),添加到副本中,然后将其分配回状态,我将从后端获取直接响应并将其分配给状态,但是擦除摆脱了我以前在那里的任何状态。此外,我在 .then 逻辑行中有 setState() 函数,我希望它能够解决在实际从服务器获取信息之前分配状态的问题。这种用法有错吗?
  • 更新:我应用了这个修复来测试它,但仍然有同样的错误。数组在那里,但是数组在 0 处的索引是未定义的。
【解决方案2】:

更新:我能够找到问题所在。

问题出在 .then 字符串上。如果您使用 .then 但没有将参数传递给您要执行的代码,看起来 .then 部分将被省略,它会在不等待的情况下运行,这就是导致事情无序运行的原因。

我相信文档(here) 中的相关行是

如果省略一个或两个参数或提供非函数,则将缺少处理程序,但不会产生任何错误。如果随后被调用的 Promise 采用了没有处理程序的状态(实现或拒绝),则返回的 Promise 采用被调用的原始 Promise 的最终状态。

我的更新和工作的 getVocab() 函数:

     var newVocab = [];
     if(this.state.vocabulary == null){
       newVocab = newVocab;
     }
     else{
       newVocab = this.state.vocabulary;
     }
     this.props.HandleFetch("GET", this.props.backLink + "vocab")
      .then(r => JSON.parse(r))
      .then(data => {newVocab.push(data[0]);
                     this.setState({vocabulary:newVocab})}) 
       //Outputs correctly due to 'data' argument

   }

感谢所有评论或帮助我的人。

【讨论】:

    猜你喜欢
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 2021-08-06
    相关资源
    最近更新 更多