I have the following code, that loads a random user from an API.
On load, it shows the first name of the fetched user.
Now I want to fetch a new user when clicking the ‘Generate user’ button, but it’s not triggering the useEffect.
I thought I could trigger a refresh by passing the generate var to the dependency array in the useEffect, but it’s not working. Should I make generate part of the state? That seems counter-intuitive for a simple toggle.
Any help / tips appreciated!
import { useEffect, useState } from "react";
const Async = () => {
let generate = false;
const [user, setUser] = useState({name: ''});
useEffect(() => {
fetch('https://randomuser.me/api/?results=1')
.then(response => response.json())
.then(data => setUser({...user, ['name']: data.results[0].name.first}))
.catch(error => console.error(error));
}, [generate]);
function newUser()
{
generate = !generate;
}
return <>
<button onClick={newUser}>Generate user</button>
<div>User {user.name}</div>
</>;
};
>Solution :
You could move generate into a React state that is toggled and triggers a rerender, but it would be better to just abstract the fetch call into a callback that is called by the button element’s onClick handler. Call the function once in a mounting useEffect hook.
import { useEffect, useState } from "react";
const Async = () => {
const [user, setUser] = useState({ name: '' });
const generate = () => {
fetch('https://randomuser.me/api/?results=1')
.then(response => response.json())
.then(data => setUser(user => ({
...user,
name: data.results[0].name.first
})))
.catch(error => console.error(error));
};
// Call once when the component mounts
useEffect(() => {
generate();
}, []);
return (
<>
<button onClick={generate}>Generate user</button>
<div>User {user.name}</div>
</>
);
};