0

I'm trying to fecthing all API which contain in array. I use promise all to get the data and I finally get the data that I wanted. But, I have a problem to store result into new array or object from Promise.all function. How I can store data from API on stateless component in React. So the expectaion in this approch I can call it like {dataJSON.title}

import React from 'react'

const ApiComponent = (props) => {

  // props.film content
  //["https://swapi.co/api/films/2/","https://swapi.co/api/films/6/"]

  let dataJSON = []

  Promise.all(
    props.film.map(url =>
      fetch(url)
      .then(response => response.json())
      .then(
        parseJSON => ({
          title: parseJSON.title,
          episode: parseJSON.episode
        })
      )
      .then(
        dataJSON => push[dataJSON]
      )
    ))


  return (

    // expecting return will call like this 
    {
      dataJSON.title
    }

  )
}

export default ApiComponent;
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • 2
    Short answer is you can't. Promises are asynchronous. You need to use state or pass data in from higher level – charlietfl Sep 05 '18 at 13:26
  • is stateless really the right approach here? Everytime this component gets rendered, it will fire the network requests! If you want to separate the concerns, you can split the component into a [container and a presentation component](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). – dubes Sep 05 '18 at 13:26
  • I notice it's asynchronous, that's why I want to store into new object/array so I can call data from new object/array. That was I thinking if it's possible to do with this approach – Widdesto Yudistiro Sep 05 '18 at 13:38

1 Answers1

0

If your component is "stateless", then it shouldn't be storing anything by definition, so it seems like the best thing to do is to provide a handler like onAjaxComplete to be called with results when results are successfully retrieved.

const ps = {
  films: ["https://swapi.co/api/films/2/","https://swapi.co/api/films/6/"],
  onAjaxComplete: (results) => console.log('Here are the results:', results)
};

const ApiComponent = (props) => 
    Promise.all(props.films.map(url => fetch(url)
      .then(response => response.json())
      .then(json => ({
        title: json.title,
        episode: json.episode_id
      }))))
      .then(results => props.onAjaxComplete(results));

ApiComponent(ps);

The onAjaxComplete prop would take a function that would handle results when they came back, and if you're using Redux or something like that, you could pass results on to a store or whatever at that point.

Alternately, you might explore using async/await if you wanted to try to return the resolved promise values directly from the function. But really async/await is just syntactic sugar to make dealing with async code feel more imperative.

EDIT: as others mention in comments above, depending on how this integrates with other things, you might consider not making this stateless to avoid unnecessary requests. Or don't treat it as a component at all, just make it a function that takes a list of URLs to call, and a callback for handling results.