admin管理员组

文章数量:1391929

Hi I am fetching data from an api and I would like to take the data and render it to the dom but I am the error "Uncaught TypeError: Cannot read property 'map' of undefined at Topicselect.render"

Here is essentially what I am doing, although I have abstracted away anything that is not directly relevant to the question, such as actual topic names, imports, etc :

class Topics extends Component{
   constructor(props){
     super(props);
     this.state = {
       topics: []
     }
   }
    ponentWillMount(){
        fetch('/api').then((res)=>r.json().then((data)=>{
               // push topics into this.state.topics somehow
        }) 
       console.log(this.state.topics) //returns ['topic1','topic2','topic3'];
    } 
   render(){
     const list = this.state.topics.map((topic)=>{
         return(<li>{topic}</li>);
     })
    return(
      <ul>
        {list}
      </ul>
     )
    }
}

Can anyone tell me how to fix this? I saw an answer on here that said to use ponentDidMount instead of ponentWillMount but that isn't working for me

Hi I am fetching data from an api and I would like to take the data and render it to the dom but I am the error "Uncaught TypeError: Cannot read property 'map' of undefined at Topicselect.render"

Here is essentially what I am doing, although I have abstracted away anything that is not directly relevant to the question, such as actual topic names, imports, etc :

class Topics extends Component{
   constructor(props){
     super(props);
     this.state = {
       topics: []
     }
   }
    ponentWillMount(){
        fetch('/api').then((res)=>r.json().then((data)=>{
               // push topics into this.state.topics somehow
        }) 
       console.log(this.state.topics) //returns ['topic1','topic2','topic3'];
    } 
   render(){
     const list = this.state.topics.map((topic)=>{
         return(<li>{topic}</li>);
     })
    return(
      <ul>
        {list}
      </ul>
     )
    }
}

Can anyone tell me how to fix this? I saw an answer on here that said to use ponentDidMount instead of ponentWillMount but that isn't working for me

Share Improve this question edited Nov 6, 2019 at 17:15 Emile Bergeron 17.4k5 gold badges85 silver badges131 bronze badges asked Jul 27, 2017 at 4:46 moeshmoesh 3191 gold badge6 silver badges13 bronze badges 2
  • The error you posted does not seem to fit your code. Do you have a class "Topicselect"? – Philipp Commented Jul 27, 2017 at 5:42
  • Possible duplicate of How to set state of response from axios in react – Emile Bergeron Commented Nov 6, 2019 at 17:16
Add a ment  | 

2 Answers 2

Reset to default 2

You are missing a closing bracket ) after the fetch and it's indeed remended to use ponentDidMount() instead of ponentWillMount() for fetching data from an API.

Also don't forget to use this.setState({ topics: data.howeverYourDataIsStructured }); after you receive the data from the API to ensure a rerender of the ponent.

class Topics extends Component{
  constructor(props){
    super(props);
    this.state = {
      topics: []
    }
  }

  ponentDidMount() {
    fetch('/api').then((res)=>r.json().then((data)=>{
      this.setState({ topics: data.topics });
    }));
    console.log(this.state.topics) //returns [];
  }

  render() {
    console.log(this.state.topics) //returns [] the first render, returns ['topic1','topic2','topic3'] on the second render;
    return(
      <ul>
        {this.state.topics.map(topic => (
          <li>{topic}</li>
        ))}
      </ul>
    )
  }
}

Make sure you use setState() to update your state, otherwise render() won't be triggered to update the dom. Also make sure you don't just overwrite the current state but add your new topics to the old ones. (not relevant for this case, but still important to mention)

One way to do it would be:

ponentDidMount() {
    var currentTopics = this.state.topics;
    fetch('/api').then((res) => r.json().then((data) => {
            currentTopics.push(data);
        }));
    this.setState({'topics': currentTopics});
}

But you can also call setState() inside the loop. setState() does not work synchronously so it will first wait if there are some other changes to be made before it will actually execute the changes and then trigger render.

ponentDidMount() {
    fetch('/api').then((res) => r.json().then((data) => {
        this.setState((state) => ({ topics: [...state.topics, data]}));
    }));
}

本文标签: javascriptFetch data and then render it to dom ReactStack Overflow