最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React .map is not a function - Stack Overflow

programmeradmin0浏览0评论

I'm trying to learn React and I'm a beginner when it comes to Javascript. Right now I'm working on an app that is fetching data from Flickr's API. The problem is that when I try to use the map method on the props in the Main.js component I get an error saying "Uncaught TypeError: this.props.photos.map is not a function". After searching here on Stackoverflow I think the problem is that this.props are javascript objects and not an array. The problem is that I can't figure out how to make it an array. Can anyone explain what I'm doing wrong?

My code:

class App extends Component {

  constructor() {
  super();
  this.state = {

  }
}

componentDidMount() {

let apiKey = 'xxxxxxxxxxxxxxxxxx';
let searchKeyword = 'nature';
let url = `/ 
           rest/?api_key=${apiKey}&method=flickr.photos.
           search&format=json&nojsoncallback=1&&per_page=50
           &page=1&text=${searchKeyword}`;

fetch(url)
  .then(response => response.json())
  .then(data => data.photos.photo.map((x) => {

    this.setState({
      farm: x.farm,
      id: x.id,
      secret: x.secret,
      server: x.server})
   // console.log(this.state)
  }))
 }

    render() {
      return (
        <div className="App">
          <Header />
          <Main img={this.state.photos} />
          <Navigation />
        </div>
      );
    }
  }

  export default class Main extends Component {

  render() {

    return(
      <main className="main">
        {console.log(this.props.photos)}
      </main>
    )
  }
 }

Edit: Why is this.props.img undefined first?

Screen shot from console.log(this.props.img)

I'm trying to learn React and I'm a beginner when it comes to Javascript. Right now I'm working on an app that is fetching data from Flickr's API. The problem is that when I try to use the map method on the props in the Main.js component I get an error saying "Uncaught TypeError: this.props.photos.map is not a function". After searching here on Stackoverflow I think the problem is that this.props are javascript objects and not an array. The problem is that I can't figure out how to make it an array. Can anyone explain what I'm doing wrong?

My code:

class App extends Component {

  constructor() {
  super();
  this.state = {

  }
}

componentDidMount() {

let apiKey = 'xxxxxxxxxxxxxxxxxx';
let searchKeyword = 'nature';
let url = `https://api.flickr.com/services/ 
           rest/?api_key=${apiKey}&method=flickr.photos.
           search&format=json&nojsoncallback=1&&per_page=50
           &page=1&text=${searchKeyword}`;

fetch(url)
  .then(response => response.json())
  .then(data => data.photos.photo.map((x) => {

    this.setState({
      farm: x.farm,
      id: x.id,
      secret: x.secret,
      server: x.server})
   // console.log(this.state)
  }))
 }

    render() {
      return (
        <div className="App">
          <Header />
          <Main img={this.state.photos} />
          <Navigation />
        </div>
      );
    }
  }

  export default class Main extends Component {

  render() {

    return(
      <main className="main">
        {console.log(this.props.photos)}
      </main>
    )
  }
 }

Edit: Why is this.props.img undefined first?

Screen shot from console.log(this.props.img)

Share Improve this question edited Jun 15, 2017 at 20:22 Tose asked Jun 15, 2017 at 18:21 ToseTose 831 gold badge1 silver badge5 bronze badges 4
  • what is photo? map is a method of Array. – Davin Tryon Commented Jun 15, 2017 at 18:22
  • 'I get an error saying "Uncaught TypeError: this.props.photos.map is not a function"' this.props.photos.map doesn't appear anywhere in your quoted code. data.photos.photo.map does, did you mean that? – T.J. Crowder Commented Jun 15, 2017 at 18:25
  • 1 Separately: You're calling map and within the map callback, you're calling setState and not returning any value, so you're mapping every entry to undefined; you're also not using the return value of map at all (you're returning it out of then, but nothing uses the resulting promise, so it goes unused). You almost certainly don't want to repeatedly call setState like that. – T.J. Crowder Commented Jun 15, 2017 at 18:27
  • Does the URL really have linebreaks? That would not work properly. – Patrick Roberts Commented Jun 15, 2017 at 18:30
Add a comment  | 

3 Answers 3

Reset to default 7
fetch(url)
  .then(response => response.json())
  .then(data => data.photos.photo.map((x) => {

    this.setState({
      farm: x.farm,
      id: x.id,
      secret: x.secret,
      server: x.server})
  }))

What is happening is that your map function in your promise is resetting the component's state for every photo that is returned. So your state will always be the last object in your list of returned photos.

Here is a more simplified example of what I am referring to

const testArray = [1,2,3,4];

let currentState;

testArray.map((value) => currentState = value)

console.log(currentState);

What you want to do is this

const testArray = [1,2,3,4];

let currentState;

//Notice we are using the return value of the map function itself.
currentState = testArray.map((value) => value)

console.log(currentState);

For what you are trying to accomplish, you want your state to be the result of the map function (since that returns an array of your results from the map). Something like this:

fetch(url)
  .then(response => response.json())
  .then(data => 
    this.setState({
      photos:
        data.photos.photo.map((x) => ({
          farm: x.farm,
          id: x.id,
          secret: x.secret,
          server: x.server
        }))
     })
   )

This error might also happen if you try to provide something else other than the array that .map() is expecting, even if you declare the variable type properly. A hook-based example:

const [myTwinkies, setMyTwinkies] = useState<Twinkies[]>([]);

useEffect(() => {
  // add a twinky if none are left in 7eleven
  // setMyTwinkies(twinkiesAt711 ?? {}); // ---> CAUSES ".map is not a function"
  setMyTwinkies(twinkiesAt711 ?? [{}]); 
}, [twinkiesAt711, setMyTwinkies]);

return (<ul>
  {myTwinkies.map((twinky, i)=> (
    <li key={i}>Twinky {i}: {twinky?.expiryDate}</li>
  ))}
</ul>)

Just check the length of the array before going for the map. If the len is more than 0 then go for it, otherwise, ignore it.

data.photos.photo.map.length>0 && data.photos.photo.map(........)
发布评论

评论列表(0)

  1. 暂无评论