Undefined
Undefined

Reputation: 1021

Best way to fetch the data from API

I am making a simple react application in which I am in the need to display user list in select dropdown.

This user list comes from api.

So I am using Context API in my application and I have made a context and made the api call inside the context.

context.js

import React from "react";
import axios from "axios";

export const UserContext = React.createContext();

export function Provider({ children }) {
  const getUsers = () => {
    return axios.get(`https://randomuser.me/api/?results=10`).then((res) => {
      return res;
    });
  };

  return (
    <UserContext.Provider value={{ usersList: getUsers() }}>
      {children}
    </UserContext.Provider>
  );
}

users.js

-> Just including context where user data has been fetched and included react-select for dropdown.

-> Using useContext getting the promise value and inside useEffect hook getting the response and storing it in a state variable setUsers

-> In render method returning the select box values with the fetched users list as dropdown.

import React, { useContext, useEffect, useState } from "react";
import Select from "react-select";
import { UserContext } from "../context";

const Users = () => {
  const { usersList } = useContext(UserContext);

  const [users, setUsers] = useState([]);

  const getUsers = () => {
    usersList.then((users) => {
      setUsers(users.data.results);
    });
  };

  useEffect(() => {
    getUsers();
  }, []);

  return (
    <div>
      <p> Below user list in select box is called from API </p>
      <Select
        value={""}
        name="user"
        options={users}
        getOptionLabel={(option) => option.name.first}
        getOptionValue={(option) => option.id.value}
        className="basic-multi-select"
      />
    </div>
  );
};

export default Users;

Working example:

Edit React Context API (forked)

Query:

-> This works fine but in my real application this leads to multiple api calls.

-> I have checked in network tab and it has been called for at least 50 times and I feel that this will be a big issue regarding peroformance.

So I would like to know if there is a much better and standard way of implementing this in order to avoid memory leaks and multiple calls for an api fetch?

I am suspecting whether this line,

<UserContext.Provider value={{ usersList: getUsers() }}>

causing the real issue as I am calling getUsers() method with parathesis () but if I remove it the it doesn't get executed..

Please kindly help me and thanks in advance..

Upvotes: 1

Views: 371

Answers (1)

iagowp
iagowp

Reputation: 2494

You can store the user list in an array, and have your components call getUsers on mount. Then just use users wherever you need

export function Provider({ children }) {
  const [users, setUsers] = useState([]);
  const getUsers = () => {
    if (!users.length) {
      axios.get(`https://randomuser.me/api/?results=10`).then((res) => {
        setUsers(res.data.results);
      });
    }
  };

  return (
    <UserContext.Provider value={{ usersList: users, getUsers }}>
      {children}
    </UserContext.Provider>
  );
}

On User.js

const Users = () => {
  const { usersList, getUsers } = useContext(UserContext);

  useEffect(() => {
    getUsers();
  }, [getUsers]);

  return (
    <div>
      <p> Below user list in select box is called from API </p>
      <Select
        value={""}
        name="user"
        options={users}
        getOptionLabel={(option) => option.name.first}
        getOptionValue={(option) => option.id.value}
        className="basic-multi-select"
      />
    </div>
  );
};

Upvotes: 1

Related Questions