无法访问状态内的对象

时间:2019-08-20 05:21:40

标签: reactjs

我有一个组件,该组件使用axios来访问PubMed api(位于componentDidMount中),检索一些发布ID,然后将其存储为“ idlist”状态。然后调用第二个函数(addPapers),该函数传入此ID列表,并进行第二次api调用,以检索每个ID的更多详细信息(标题,期刊,作者)。所有这些似乎都可以正常工作,当我使用React工具检查状态时,有一个数组(“ paperList”)充满了具有预期key:value对的对象。但是,当我尝试映射此数组并访问render函数中的对象(即paper.title,paper.author,paper.journal)中的值时,它们将返回未定义状态。我使用反应时间不长,怀疑我犯了一个基本错误,但无法弄清楚。

我已经尝试过console.logging每个步骤,并且预期的数据处于状态并且在React工具中是正确的

import axios from 'axios'
import './App.css';
import rateLimit from 'axios-rate-limit';

class App extends Component {
  state= {
    idlist: [],
    papersList : ""
  }


  componentDidMount () {
    console.log("incomponent")
     axios.get("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmode=json&retmax=1000&term=((Australia%5Bad%5D)%20AND%20(%222019%2F07%2F01%22%5BDate%20-%20Publication%5D%20%3A%20%223000%22%5BDate%20-%20Publication%5D))%20AND%20(%22nature%22%5BJournal%5D%20OR%20%22Nature%20cell%20biology%22%5BJournal%5D%20OR%20%22Nature%20structural%20%26%20molecular%20biology%22%5BJournal%5D)")
    .then (response => 
      this.setState({idlist: response.data.esearchresult.idlist}, () => {
        this.addPapers(this.state.idlist)
      }
    ) 
  )}


    addPapers = (idlist) => {  
      if (idlist) {
        const http = rateLimit(axios.create(), { maxRequests: 6, perMilliseconds: 1000 }) 

        const list = this.state.idlist.map(id => {
          let paperObj ={};
          let paperList =[]
          http.get(`https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&retmode=json&rettype=abstract&id=${id}&api_key=9476810b14695bd14f228e63433facbf9c08`)
          .then (response2 => {
          const title = response2.data.result[id].title
          const journal = response2.data.result[id].fulljournalname
          const authorList = []
          const authors = response2.data.result[id].authors
          authors.map((author, idx) =>
            idx > 0 ? authorList.push(" " + author.name) : authorList.push(author.name))
          paperObj.title = title
          paperObj.journal = journal
          paperObj.authors = authorList.toString()
          paperList.push(paperObj) 
          })
          return paperObj
        }) 
        this.setState({papersList: list}) 
      }
    }


  render () {
    let article = ""
    if (this.state.papersList.length){
      article = this.state.papersList.map(paper =>
       console.log (paper.title)
       console.log (paper.authors)
       console.log (paper.journal)
      )
    } 

  return (
    <div className="App">
      <h1>Publications</h1>
        {article}
    </div>
  );
  }
}

export default App;

我希望当我映射到paperList并提取每篇论文时,我应该能够使用console.log(paper.title),console.log(paper.title),console.log( paper.title)。这些都返回未定义。

2 个答案:

答案 0 :(得分:2)

您在代码中遇到两个问题

1)paperList数组声明应该在映射循环之外。

2)应该返回paperList而不是paperObj

下面的工作代码对render功能进行了一些增强

codesandbox link

import React from "react";
import ReactDOM from "react-dom";
import rateLimit from "axios-rate-limit";
import axios from "axios";

import "./styles.css";

class App extends React.Component {
  state = {
    idlist: [],
    papersList: ""
  };

  componentDidMount() {
    console.log("incomponent");
    axios
      .get(
        "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmode=json&retmax=1000&term=((Australia%5Bad%5D)%20AND%20(%222019%2F07%2F01%22%5BDate%20-%20Publication%5D%20%3A%20%223000%22%5BDate%20-%20Publication%5D))%20AND%20(%22nature%22%5BJournal%5D%20OR%20%22Nature%20cell%20biology%22%5BJournal%5D%20OR%20%22Nature%20structural%20%26%20molecular%20biology%22%5BJournal%5D)"
      )
      .then(response =>
        this.setState({ idlist: response.data.esearchresult.idlist }, () => {
          this.addPapers(this.state.idlist);
        })
      );
  }

  addPapers = idlist => {
    if (idlist) {
      const http = rateLimit(axios.create(), {
        maxRequests: 6,
        perMilliseconds: 1000
      });
      let paperList = [];
      this.state.idlist.forEach(id => {
        let paperObj = {};
        http
          .get(
            `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&retmode=json&rettype=abstract&id=${id}&api_key=9476810b14695bd14f228e63433facbf9c08`
          )
          .then(response2 => {
            const title = response2.data.result[id].title;
            const journal = response2.data.result[id].fulljournalname;
            const authorList = [];
            const authors = response2.data.result[id].authors;
            authors.map((author, idx) =>
              idx > 0
                ? authorList.push(" " + author.name)
                : authorList.push(author.name)
            );
            paperObj.title = title;
            paperObj.journal = journal;
            paperObj.authors = authorList.toString();
            paperList.push(paperObj);
          })
          .then(result => {
            this.setState({ papersList: paperList });
          });
      });
    }
  };

  render() {
    return (
      <div className="App">
        <h1>Publications</h1>
        {this.state.papersList.length &&
          this.state.papersList.map(data => {
            return <div>{data.title}</div>;
          })}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

希望有帮助!

答案 1 :(得分:0)

这样做:

render () {
let article;
if (this.state.papersList.length){
  article = this.state.papersList.map(paper => <p>span>Title is {paper.title}</span></p> )
} 



return (
    <div className="App">
      <h1>Publications</h1>
        {article}
    </div>
  );
  }