I am a beginner in react and trying a basic example where I am fetching data based on what I am passing in input field , the value in input field goes as id to the API URL , Everything is working fine but this fails for a particular case . Suppose I entered 3 in input field and then click the button , First time the data shows as expected , but if I again press the get data button the UI just stuck showing Loading... I think it is related to dependency array in useEffect.
import React,{useState,useEffect} from 'react'
const FetchData = () => {
const [data,setData]=useState({})
const [value,setValue]=useState(1)
const [id,setId]=useState(1)
const [loading,setLoading]=useState(true)
const idUpdater=()=>{
setLoading(true)
setId(value)
}
useEffect(()=>{
const fetchData= async()=>{
const data=await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
const response=await data.json()
setData(response)
setLoading(false)
}
setTimeout(fetchData,2000)
},[id])
return (
<div>
<input type="text" value={value} onChange={(e)=>setValue(e.target.value)} />
<button onClick={idUpdater}>Get Data</button>
{loading?<h1>Loading...</h1>:<h1>{data.title}</h1>}
</div>
)
}
export default FetchData
I tried removing the dependency array , but it didn't work
Based on the condition you have given the code in useEffect gets only rendered when the id is different. When you press the button again the id remains same thus the code inside useEffect won't run and the loading state set in idUpdater will remain true.
A better approach to this would be calling fetch on initial mount and reusing that function on button press, as:
import React, { useState, useEffect } from "react";
const FetchData = () => {
const [data, setData] = useState({});
const [value, setValue] = useState(1);
const [loading, setLoading] = useState(true);
const idUpdater = () => {
setLoading(true);
fetchData(value);
};
const fetchData = async (pageNo) => {
const data = await fetch(
`https://jsonplaceholder.typicode.com/posts/${pageNo}`
);
const response = await data.json();
setData(response);
setLoading(false);
};
useEffect(() => {
fetchData(1);
}, []);
return (
<div>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<button onClick={idUpdater}>Get Data</button>
{loading ? <h1>Loading...</h1> : <h1>{data.title}</h1>}
</div>
);
};
export default FetchData;