I’m trying to build a project that uses infinite scrolling to display the user information in the ui taken from an external API. I’ve managed to fetch the data successfully from the API and also apply the infinite scrolling methodology after a lot of googling.
Now, I’m trying to make a dynamical routing work, so basically, when the user clicks on the card containing the user information that I’m getting from the API, It should be able to redirect to its personal page where there’s gonna be even more personal data. So, I’m using routing for that and I managed to do that as well.
But the problem is, when I’m in the url of that one specific user and trying to fetch another API that contains more personal info about the that single user, I’m getting weird bugs that I’m gonna explain below, first, let me show you my code.
function Home() {
const [items, setItems] = useState([]);
const [isFetching, setIsFetching] = useState(false);
const [page, setPage] = useState(1);
const fetchData = (setItems, items) => {
let url = `http://sweeftdigital-intern.eu-central-1.elasticbeanstalk.com/user/1/50`;
axios.get(url).then((res) => {
setItems([...items, ...res.data.list]);
console.log(res);
});
};
const moreData = () => {
let url = `http://sweeftdigital-intern.eu-central-1.elasticbeanstalk.com/user/${page}/50`;
axios.get(url).then(res => {
setItems([...items, ...res.data.list]);
setPage(page+1)
setIsFetching(false)
});
}
const isScrolling =()=>{
if(window.innerHeight + document.documentElement.scrollTop!==document.documentElement.offsetHeight){
return;
}
setIsFetching(true)
}
useEffect(()=>{
fetchData(setItems,items);
window.addEventListener("scroll", isScrolling);
return () => window.removeEventListener("scroll", isScrolling);
},[]);
useEffect(() => {
if (isFetching){
moreData();
}
}, [isFetching]);
return (
<div className="card-container">
{items.map((user,key) => (
<Card key={key} id={user.id} prefix={user.prefix} name={user.name} lastName={user.lastName} image={user.imageUrl} job={user.title}/>
))}
</div>
);
}
This is Home.jsx, the main path, where I’m implementing the infinite scrolling methodology and mapping the state that contains an array that I get from the API. When the user clicks on the card, It redirects them to User.jsx path :
export default function Users() {
const params = useParams();
const [users, setUsers] = useState({})
useEffect(()=>{
async function fetchData(){
const res = await axios(`http://sweeftdigital-intern.eu-central-1.elasticbeanstalk.com/user/${params.id}`);
console.log(res.data);
setUsers(res.data);
}
fetchData()
},[])
return (
<div className='container'>
<img src={users.imageUrl}/>
<h1 className=''>Info</h1>
<div className='card-div'>
<div className='name-div'>
<h3 style={{fontWeight:"bold", fontSize:"25px"}}>{users.prefix} {users.name} {users.lastName}</h3>
<h3 style={{fontStyle:"italic", fontSize:"20px"}}>{users.title}</h3>
</div>
<div className='details-div'>
<h3>Email: {users.email}</h3>
<h3>Ip Address: {users.ip}</h3>
<h3>Job Area: {users.jobArea}</h3>
<h3>Job Type: {users.jobType}</h3>
</div>
</div>
<h1 className='adress-h1'>Address</h1>
<div className='address-div'>
<h3>{users.company.name} {users.company.suffix}</h3>
<h3>City: {users.address.city}</h3>
<h3>Country: {users.address.country}</h3>
<h3>State: {users.address.state}</h3>
<h3>Street Address: {users.address.streetAddress}</h3>
<h3>ZIP: {users.address.zipCode}</h3>
</div>
</div>
)
}
So basically, If I comment out the code in div with container class in Users.jsx, the fetching functionality works and the data gets logged in the console as written in the code. After that, If I uncomment, everything works and fine and I’m able to see the UI in the page with the correct data taken from the API.
But When I reload the page, It disappears, the page crashes and get a lot of typeErrors, I’m guessing that when the page renders for the first time, the data taken from the API doesn’t exist first and thats why the web crashes, but I don’t know how to fix that. I’ll appreciate any tips and help, thank you in advance!
>Solution :
An explanation of what’s happening is that your JSX is being rendered before the data is fetched, which is a normal behaviour in React, cause the callback of the useEffect and updating a state are asynchronous tasks.
One way to resolve this issue is by doing so:
- Change your state definition inside
User.jsxto this:
// this way it initiates users to undefined const [users, setUsers] = useState()
- Before that
returnyou have insideUser.jsxadd this piece of code to show a loader while the data is being fetched:
if(!users) return <p>Fetching...</p>