Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

320
Vistas
'if else statement' doesn't work properly when importing data as props in React

if else statement inside useEffect doesn't work as expected. else is executed before the code inside the if is executed completely. I've commented out what I'm expecting in the code. someData prop is the data fetched from the server using the fetch API in the parent component.

import { useState, useEffect } from "react";

const App = ({ someData }) => {
  const [text, setText] = useState(0)
  const [lastNumber, setLastNumber] = useState(0)
  useEffect(() => {
    if (!someData) {
      (async () => {
        const res = await fetch(`https://xxx-xxx......`);
        const myJson = await res.json();
        const _lastNumber = myJson.number // 1000
        setLastNumber(_lastNumber)
        console.log(lastNumber) // 1000, appear in the console second
      })();
    } else {
        console.log(lastNumber) // 0, appear in the console first
        setText(
          lastNumber - someData.number // 0 - 100 (I expect "1000 - 100".)
        );
    }
  }, [someData, lastNumber]);

  if (!someData) {
    return (
      <div>
        <h1>Loading</h1>
      </div>
    )
  } else {
    return (
      <div>
        <h1>{text /* -100 (I expect "900".) */}</h1>
      </div>
    );
  }
};

export default App;

If I write code like this using some tricks, it takes a long time to load but works as I want.

import { useState, useEffect } from "react";

const App = ({ someData }) => {
  const [text, setText] = useState(0)
  const [lastNumber, setLastNumber] = useState(0)
  useEffect(() => {
    if (!someData) {
      (async () => {
        const res = await fetch(`https://xxx-xxx......`);
        const myJson = await res.json();
        const _lastNumber = myJson.number // 1000
        setLastNumber(_lastNumber)
        console.log(lastNumber)
      })();
    } else {
      if (lastNumber !== 0) {
        console.log(lastNumber) 
        setText(
          lastNumber - someData.number
        );
      }
    }
  }, [someData, lastNumber]);

  if (!someData) {
    return (
      <div>
        <h1>Loading</h1>
      </div>
    )
  } else {
    return (
      <div>
        <h1>{text /* 900 */}</h1>
      </div>
    );
  }
};

export default App;

But I don't know why it works the way that I want and if it's a good way to do it. Please let me know the better way.

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

You need to move effect in dedicated async function, in order to await part of the execution. In your current solution your effect is synchronous and IIFE you declared will be executed synchronously thus can cause unexpected behaviour of effect.

Rewrite to this(in order to await code execution):

 const doSomething = async () => {
   if (!someData) {
      const res = await fetch(`https://xxx-xxx......`); // NOW YOU CODE WILL WAIT
      const myJson = await res.json();
      const _lastNumber = myJson.number; // 1000
      setLastNumber(_lastNumber);
      console.log(lastNumber); // YOU CAN NOT EXPECT TO READ NEW VALUE IMMEDIATELY, THIS WILL LOG OLD VALUE FOR lastNumber
    } else {
      console.log(lastNumber); // 0, appear in the console first
      setText(
      lastNumber - someData.number // 0 - 100 (I expect "1000 - 100".)
      );
    }
  };

 useEffect(() => {
   doSomething();

 }, [someData, lastNumber]);

Also, in console.log(lastNumber) part you can not expect to log latest value, one that was set in line before, because state update is async and state is accessed from closure meaning you will access new value from lastNumber but only after rerender.

about 4 years ago · Juan Pablo Isaza Denunciar

0

Yeah! Async functions... )) Read this article for explanations.

The issue here is that the first argument of useEffect is supposed to be a function that returns either nothing (undefined) or a function (to clean up side effects). But an async function returns a Promise, which can't be called as a function! It's simply not what the useEffect hook expects for its first argument.

enum LoadingStatusEnum {
    INACTIVE = -1,
    ACTIVE = 1,
    ERROR = 0,
}

export default function Example({someData}): JSX.Element {
    const [text, setText] = useState(0);
    const [lastNumber, setLastNumber] = useState(0);
    const [loadingStatus, setLoadingStatus] = useState<LoadingStatusEnum>(LoadingStatusEnum.INACTIVE);
    useEffect(() => {
        const fetchData = async () => {
            setLoadingStatus(LoadingStatusEnum.ACTIVE);
            const response = await fetch('API action here');
            const json = await response.json();
            setLastNumber(json.number);
        };

        if (!someData && loadingStatus !== LoadingStatusEnum.ACTIVE) {
            fetchData()
                .then(() => {
                    setLoadingStatus(LoadingStatusEnum.INACTIVE);
                })
                .catch(() => {
                    setLoadingStatus(LoadingStatusEnum.ERROR);
                });
        } else {
            setText(lastNumber - someData.number);
        }
    }, [someData, lastNumber]);

    const renderTitle = () => {
        let title = String(text);
        if (loadingStatus === LoadingStatusEnum.ACTIVE) {
            title = 'Loading';
        }
        if (loadingStatus === LoadingStatusEnum.ERROR) {
            title = 'Error';
        }

        return title;
    };

    return (
        <div>
            <h1>
                {renderTitle()}
            </h1>
        </div>
    );
}

 
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda