Home > Enterprise >  uncaught TypeError: this.state.posts.map is not a function
uncaught TypeError: this.state.posts.map is not a function

Time:08-10

I am using react to try to populate data on render during a fetch call but am running into a problem. When trying to run a regular fetch api call using placeholder information everything works just fine. However, when trying to get the "weather" or main sections of data to populate I am having a problem. The specific error I am receiving is "uncaught TypeError: this.state.posts.map is not a function"

 import logo from './logo.svg';
import './App.css';
import React from 'react';

class App extends React.Component {
  state = {  
    posts: [],
   
  };
  componentDidMount() {
    fetch("https://mm214.com/demo.php")

      .then(response => response.json())
      .then(posts => {console.log(posts)
        this.setState({ posts });
      }
      )
      .catch(error => console.error(error));
  }
  render() {
    return (
      
         <header> 
         <h1>Weather</h1>
        <li>
        {this.state.posts.map(post => (           
           <li key={post}>{post.main} {post.temp}</li>
          )
          )
          }
         </li>


      </header>
    
        
      
    );
  }
}

export default App;

CodePudding user response:

the api doesn't return an array i tried calling it and it returns this

{"coord":{"lon":-117.1573,"lat":32.7153},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"base":"stations","main":{"temp":296.62,...`

Check how your data should be because map only works on arrays. If you want main and temp try accessing them manually post.weather.main for example

CodePudding user response:

Your API response is a single JSON, not an array. If it is supposed to respond in both ways (either a single object or an array of objects), you can do a type check and update the state accordingly.

class App extends React.Component {
  state = {
    posts: []
  };
  componentDidMount() {
    fetch("https://mm214.com/demo.php")
      .then((response) => response.json())
      .then((posts) => {
        if (Array.isArray(posts)) {
          this.setState({ posts });
        } else if (typeof posts === "object") {
          this.setState({ posts: [posts] });
        }
      })
      .catch((error) => console.error(error));
  }

  render() {
    return (
      <header>
        <h1>Weather</h1>
        <ul>
          {this.state.posts.map((post) => (
            <li key={post}>
              {post.name} {post.main.temp}
            </li>
          ))}
        </ul>
      </header>
    );
  }
}

ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

CodePudding user response:

If you want the weather from the API then i think you should try to map this.posts.weather instead of this.posts, since this.posts is an object which contains the array "weather". Your code could for example look something like this

import logo from './logo.svg';
import './App.css';
import React from 'react';

class App extends React.Component {
  state = {  
    posts: [],
   
  };
  componentDidMount() {
    fetch("https://mm214.com/demo.php")
      .then(response => response.json())
      .then(posts => {console.log(posts)
        this.setState({ posts });
      }
      )
      .catch(error => console.error(error));
  }
  render() {
    return (
      
         <header> 
         <h1>Weather</h1>
        <li>
        {(this.state.posts.weather) ?
            this.state.posts.weather.map(post => (           
               <li key={post}>{post.main} {post.temp}</li>
            ) :
            "No weather data available"
         )}
         </li>
      </header>
  • Related