Context: I am retrieving data about tutors from an API endpoint using Axios GET request. It is intended to be processed and sent to other components within the application.
Problem: I am currently using an useEffect() hook in my main App() function to initiate the GET request. I am storing the response onto a useState() hook for access at a later point in the code. While I can see the API response by logging within the useEffect code segment, I am not able to access the response oustide of it. This data state variable isn’t populated with the JSON.
My Understanding: I suspect that the state variables are being accessed before it is populated by the API response in the useEffect() hook code segment. Or it could be that setTutors() isn’t working for some reason.
Code:
function App() {
const [ searchTerm, setSearchTerm ] = useState("");
const [ sorted, setSorted] = useState(false);
const [ data, setTutors ] = useState([]);
useEffect( () => {
const retrieveData = async () => {
const resp = await axios.get('API URL Call');
console.log("Response: " + JSON.stringify(resp.data.body));
setTutors(JSON.stringify(resp.data.body)); //NOT Storing Value into Data
}
retrieveData();
});
function handleSearchTerm(event) {
setSearchTerm(event.target.value)
}
function handleSortByName() {
// sort array ascending or descending by first name
if (!sorted) {
setTutors(data.sort((a, b) => (a.name > b.name) ? 1 : -1));
setSorted(true);
} else {
setTutors(data.sort((a, b) => (a.name > b.name) ? -1 : 1));
setSorted(false);
}
}
function handleSortByDept() {
// sort array ascending or descending by dept name
if (!sorted) {
setTutors(data.sort((a, b) => (a.department > b.department) ? 1 : -1));
setSorted(true);
} else {
setTutors(data.sort((a, b) => (a.department > b.department) ? -1 : 1));
setSorted(false);
}
}
const filteredTutors = data.filter(tutor => tutor.first_name.toLowerCase().startsWith(searchTerm.toLowerCase()));
//TODO: search by category
return (
<div>
<Header/>
<Layout>
<h1 className="title text-5xl text-gray-800 mt-16">Tutor Directory</h1>
<p className="mb-16 text-md">Search for an tutor or sort by Name or Category.</p>
{/*the handleSearchTerm method and searchTerm state get passed down to the Navigation component via props with the onSearch and searchTerm props*/}
<Navigation
onSearch={handleSearchTerm}
searchTerm={searchTerm}
handleSortByName={handleSortByName}
handleSortByDept={handleSortByDept}
/>
{/* the employees array gets the filteredEmployees data via the data prop */}
<TutorCardList data={filteredTutors}/>
{/* <GetRequestHooks /> */}
<Footer/>
</Layout>
</div>
)
}
export default App;
Errors:
(1) Dependent code on the state variable not working
(2) Empty Data on Debugger
I referred to other StackOverFlow questions, didn’t find it much helpful so decided to post my own.
2
Answers
One potential issue with the code could be that the useEffect() hook is running on every render, including the initial one, due to the lack of a dependency array argument. As a result, the retrieveData() function is called every time the component updates, causing multiple API calls and potentially overwriting the state variable with incomplete data.
To address this issue, you can add an empty dependency array argument to the useEffect() hook, so that it only runs once on the initial render. This way, the retrieveData() function is only called once to fetch the data and update the state variable with the complete response.
You should not convert the response JSON to string before setting in the state.
to
Also, you should not modify the origin state while sorting the data
to