Afroditis de Noronhas
Afroditis de Noronhas

Reputation: 11

How to render an asynchronous function in reactJS?

My problem is as follows:

I have an asynchronous function that makes a mysql request and, depending on the result of the request, returns a different DIV.

const GetData = async (idAluno, disciplina) => {
  variavel = await confereInicial(idAluno, disciplina.id);
  //console.log(variavel); imprime direitinho, sem problemas

  if (variavel.data.length === 0) {
    return (
      <DivCheckBox
        dads={dados}
        nomeDisciplina={disciplina.title}
        labelDisciplina={disciplina.label}
        id={disciplina.id}
        inicial={0}
      />
    );
  } else {
    return (
      <DivCheckBox
        dads={dados}
        nomeDisciplina={disciplina.title}
        labelDisciplina={disciplina.label}
        id={disciplina.id}
        inicial={1}
      />
    );
  }
};

And this function is called several times (via a map) in the rendering part of the screen. Thus:

return (
  <div>
    {dados.state.nodesPadrao.map((p) => {
      return <GetData idAluno={1} disciplina={p} />;
    })}
  </div>
  ...
);

The problem is that when I compile, it appears "objects are not valid as react child (found: object Promise). If you want to render a collection of children, use an array instead.

What do I do?

Upvotes: 1

Views: 48

Answers (2)

Dyvd
Dyvd

Reputation: 77

I had the same problem yesterday. You shouldn't do async stuff in a render function. You should either relay on the state or props.

Upvotes: 0

AKX
AKX

Reputation: 168966

You need to understand the difference between a function (GetData()) and a function component (<GetData .../>).

Function components can't be async, since they implicitly always return a Promise, and you can't return a Promise from a component since you can't render a promise.

You'll need to use the useEffect hook to load the data at component mount time, then render things once it's loaded:

const GetData = ({idAluno, disciplina}) => {
  const [variavel, setVariavel] = React.useState(null);
  React.useEffect(() => {
    confereInicial(idAluno, disciplina.id).then(setVariavel);
  }, [idAluno, disciplina.id]);
  if (variavel === null) {
    // Still loading? You could also return `null` to not render anything.
    return <>Loading</>;
  }
  return (
    <DivCheckBox
      dads={dados}
      nomeDisciplina={disciplina.title}
      labelDisciplina={disciplina.label}
      id={disciplina.id}
      inicial={variavel.data.length === 0 ? 0 : 1}
    />
  );
};

Upvotes: 1

Related Questions