Ranga B.
Ranga B.

Reputation: 667

React: map is not a function

I am making my first steps with react and I'm struggling with the error message:

this.state.items.map is not a function

I already know that map is only a member of an array but not of objects. In the constructor of my App-class I initialized items[] explicit to an array.

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

class HelloComponent extends React.Component {
  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

class App extends Component {
  constructor() {
    super();
    this.state = { items: [] };
  }

  componentDidMount() {
    fetch(`http://example.com/api`)
      .then(result => {
        this.setState({ items: result.json() });
      }
      );
  }

  render() {
    var listItems = this.state.items.map(item => <HelloComponent name={item.name} />); // crash!!!

    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.

        {listItems}

        </p>
      </div>
    );
  }
}

export default App;

I don't know what happens. I have the suspicion that the call to result.json() may override my array with an promise but I have no idea how to implement it correctly.

Upvotes: 0

Views: 1150

Answers (2)

Leeroy_Wonkledge
Leeroy_Wonkledge

Reputation: 351

i suggest you a way to achieve your goal

import request from 'request' // obtain by npm install --save request
class App extends Component {
    constructor() {
    super();
        this.state = { items: [] };
    }

componentDidMount() {
    request(`http://example.com/api`, (error, response, body) => {
        this.setState({ items: JSON.parse(body) };
    });
}

render() {
    var listItems = this.state.items.map(item => <HelloComponent name=
    {item.login} />); // worked!!!

return (
  <div className="App">
    <header className="App-header">
      <img src={logo} className="App-logo" alt="logo" />
      <h1 className="App-title">Welcome to React</h1>
    </header>
    <p className="App-intro">
      To get started, edit <code>src/App.js</code> and save to reload.

    {listItems}

    </p>
  </div>
);
}
}

Upvotes: 1

casraf
casraf

Reputation: 21694

I think your json response is the one overwriting the regular array, you should setState only from inside the json promise:

fetch(`http://example.com/api`)
  .then(result => {
    result.json().then(json => this.setState({ items: json }))
  }
);

Or, if you can support async/await, you can just await the result:

fetch(`http://example.com/api`)
  .then(result => {
    this.setState({ items: await result.json() })
  }
);

Upvotes: 2

Related Questions