Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

312
Visualizações
'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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda