Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: How do I move my ajax api call into a separate component?

Here is a typical container component that is working perfectly well:

const API = 'https://randomuser.me/api/?results=5';
class App extends Component {

    constructor(props) {
      super(props);
      this.state = { profiles: [] };
    }

    componentDidMount() {
      this.fetchProfiles();
    }

    fetchProfiles() {
      let url = API;
      fetch(url)
        .then( (res) => res.json() )
        .then( (data) => {
          let results = data.results;
          this.setState({
            profiles: results 
          });
        })
        .catch( (error) => console.log('Oops! . There Is A Problem', error) );
    }

    render() {
      // rendering child component here
    }
}

export default App;

What I am trying to do now is move the fetchProfiles function into a separate api component.

So I make a profiles.js file in an api folder in my project:

const API = 'https://randomuser.me/api/?results=5';

export function fetchProfiles() {
  let url = API;
  fetch(url)
  .then( (res) => res.json() );
}

And now my main component imports it and uses it like so:

import { fetchProfiles } from '../api/profiles.js';


const API = 'https://randomuser.me/api/?results=5';
class App extends Component {

    constructor(props) {
      super(props);
      this.state = { profiles: [] };
    }

    componentDidMount() {
      fetchProfiles.then((data) => {
        let results = data.results;
          this.setState({
            profiles: results 
          });
      });
    }

  // render call etc

But when I run the call in componentDidMount like this, I get this error: Uncaught TypeError: _profiles.fetchProfiles.then is not a function. I am trying to chain with then because the fetch api returns res.json() as a promise.

I tried wrapping fetchProfiles in a outer function, in a new promise too! But nothing works!! What am I doing wrong here? Please help with this refactoring.

like image 685
Amit Erandole Avatar asked May 29 '16 12:05

Amit Erandole


People also ask

How do you pass API data from one component to another in React?

For passing the data from the child component to the parent component, we have to create a callback function in the parent component and then pass the callback function to the child component as a prop. This callback function will retrieve the data from the child component.

How do I transfer data between components in React?

First, you'll need to create two components, one parent and one child. Next, you'll import the child component in the parent component and return it. Then you'll create a function and a button to trigger that function. Also, you'll create a state using the useState Hook to manage the data.

Where would you put Ajax calls in your React code?

Where in the component lifecycle should I make an AJAX call? You should populate data with AJAX calls in the componentDidMount lifecycle method. This is so you can use setState to update your component when the data is retrieved.

How do you transfer props from one component to another?

Sending state/props to another component using the onClick event: So first we store the state/props into the parent component i.e in which component where we trigger the onClick event. Then to pass the state into another component, we simply pass it as a prop.


2 Answers

You need to return fetch(url) itself, so you'll return a promise and then you can use then method:

const API = 'https://randomuser.me/api/?results=5';

export function fetchProfiles() {
  let url = API;

  // return the promise itself
  return fetch(url).then( (res) => res.json() );
}
like image 86
Muhammad Aref Avatar answered Sep 20 '22 02:09

Muhammad Aref


The way I fixed this was to return fetch(url) itself:

const API = 'https://randomuser.me/api/?results=5';

export function fetchProfiles() {
    let url = API;
    return fetch(url)
      .then( (response) => response.json() );
}

Then in the container component:

    componentDidMount() {
      fetchProfiles()
        .then( (data) => {
          let results = data.results;
          this.setState({
            profiles: results
          });
        });
    }

This now works!!

like image 29
Amit Erandole Avatar answered Sep 20 '22 02:09

Amit Erandole