Home > Mobile >  Reactjs: useEffect never triggered at first load
Reactjs: useEffect never triggered at first load

Time:10-03

I'm struggling with useEffect that's not triggered at app load, but is on a click on a button. here my code:

export default function Person() {

const [person, setPerson] = useState({});
const [hitRandomUser, setHitRandomUser] = useState(0);

const fetchData = setCallback(async () => {
   const api = "http://localhost/api/person/random";
   const response = await fetch(api);
   const data = await response.json();
   setPerson(data);
   console.log(data);
  }, []);

 useEffect(() => {
     fetchData();
 }, [hitRandomUser]);

const pax = {
   id: 1549,
   name: "Mikel",
   sexe: "boy",
   pop: 1
};
const onLike = () => {
    setHitRandomUser(hitRandomUser   1);
    console.log(hitRandomUser);
    console.log("liked");
 };
 return (
      {!person.id && <h1>Loading...</h1>}
      <PersonCard person={person} onLike={onLike} />
  );
}

so this code is actually crashing my app. the problem is that useEffect is never triggered with make person an empty dict and then crashed at PersonCard when it tried to fetch person.id However if I pass pax to PersonCard, everything works just fine. When I use the onLike function from PersonCard, then hitRandomUser state changes, and in that case useEffect is correctly triggered as it's a dependency. How can I make useEffect triggers at load, or setPerson so I can use it to render?

update

The issue i see is that if I use pax unstead of person to render my component like this:

return (
      <PersonCard person={pax} onLike={onLike} />
  );

I can see that the useEffect is actually rendered correctly because I can see the result of the console.log(data) with is displayed and correct. So there should be something firing an error, but I can't see it.

CodePudding user response:

In this case useEffect is not running most likely due to the error that is happening during initial render. The Component lifecycle can give you some idea of what runs when and where.

I suggest using an early return statement (in our discussion you used a standard conditional inside the JSX, which works as well, but I believe early return is a much better fit for this use case).

You can do something like placing this:

if (!persona.id) {
  return <div>Loading…</div>;
}

// Other return goes here

Right above the return statement that renders PersonCard. This will stop execution and instead display the loading message until the precondition is met, in which case React will automatically re-evaluate and re-render the component.

CodePudding user response:

ok, this actually fixed my issue:

{!person.id && <h1>Loading...</h1>}
{person.id && <PersonSwitchCard person={person} onLike={onLike} onDislike={onDisLike} />}

thanks a lot @CristianHG

  • Related