Reputation: 1021
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:
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
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