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

63
Visualizações
Read data from request which just finished

If user type id in input, I'd like to fetch post by specific id typed by user. If not, I'd like to fetch whole array of posts, and then get some id from fetched data. I know it doesn't make sense, but it just only for tests.

It doesn't work, cause useState works asynchronously. I tried few solutions, but all of them looked very ugly.

LIVE DEMO

I received an error:

Cannot read properties of undefined (reading 'id')

Cause setPosts hasn't set yet.

What is the best, clear way to handle this case?

import { useState } from "react";

export default function App() {
  const [id, setId] = useState("");
  const [post, setPost] = useState(null);
  const [posts, setPosts] = useState([]);

  const fetchPost = async (id) => {
    const res = await axios.get(
      `https://jsonplaceholder.typicode.com/posts/${id}`
    );
    setPost(res.data);
  };

  const fetchPosts = async () => {
    const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`);
    setPosts(res.data);
  };

  const onSubmit = async (e) => {
    e.preventDefault();

    if (id) {
      await fetchPost(id);
    } else {
      await fetchPosts();
      await fetchPost(posts[0].id);
    }
  };
  return (
    <div className="App">
      <form onSubmit={onSubmit}>
        <input type="text" onChange={(e) => setId(e.target.value)} />
        <button type="submit">submit</button>
      </form>
    </div>
  );
}
about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

You can treat fetchPosts as a side-effect and wrap fetchPost(posts[0].id) in a useEffect dependant on posts.

Or just use the result directly in onSubmit() (presuming you don't need posts for something else).

  const fetchPosts = async () => {
    const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`);
    // setPosts(res.data);  // this state is transitory and not used directly by the render
    return res.data;           
  };

  const onSubmit = async (e) => {
    e.preventDefault();

    if (id) {
      await fetchPost(id);
    } else {
      const posts = await fetchPosts();  // Only used as part of submit event?
      await fetchPost(posts[0].id);
    }
  };

  return (
    <div className="App">
      <form onSubmit={onSubmit}>
        <input type="text" onChange={(e) => setId(e.target.value)} />
        <button type="submit">submit</button>
      </form>
      <div>{(post && post.title) || "No post yet"}</div>
    </div>
  );
about 4 years ago · Juan Pablo Isaza Relatório

0

Just like you said useState works asynchronously , if you want to do something after mutating it you will have to use useEffect and set posts as its arguments , now whenever the posts get mutated your funcion will be run and the first index of array will be sent to the fetchPost(id),

import axios from "axios";
import "./styles.css";

import { useEffect, useState } from "react";

export default function App() {
  const [id, setId] = useState("");
  const [post, setPost] = useState(null);
  const [posts, setPosts] = useState([]);
  useEffect(() => {
    if (posts.length) {
      fetchPost(posts[0].id);
    }
  }, [posts]);
  const fetchPost = async (id) => {
    console.log(`fetching ${id}`);
    const res = await axios.get(
      `https://jsonplaceholder.typicode.com/posts/${id}`
    );
    console.log(res.data);
    setPost(res.data);
  };

  const fetchPosts = async () => {
    console.log(`fetching all posts`);
    const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`);
    setPosts(res.data);
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    if (id) {
      await fetchPost(id);
    } else {
      await fetchPosts();
      // res = await fetchPost(posts[0].id); we dont need it here it defined in useffect function
    }
  };
  const setDefaultId = (e) => {
    setId(e.target.value);
  };
  return (
    <div className="App">
      <form onSubmit={onSubmit}>
        <input type="text" onChange={(e) => setDefaultId(e)} />
        <button type="submit">submit</button>
      </form>
    </div>
  );
}

Also consider never to update state directly in your return function it will cause performance issues

about 4 years ago · Juan Pablo Isaza Relatório

0

The problem is in the method "fetchPost". Inside this method, you have two variables with the same name. "id" from the state hook, and "id" from the function parameter. You can solve the problem changing one of those variables names.

One more thing, if "id" doesn't have value, your way to get the first post won't work because the await method won't wait to the change of the state.

I have edit a bit the code to solve both problems.

import { useState } from 'react';
import axios from 'axios';

export default function App() {
  const [id, setId] = useState('');
  const [post, setPost] = useState(null);

  const fetchPost = async (idProp) => {
    const res = await axios.get(
      `https://jsonplaceholder.typicode.com/posts/${idProp}`,
    );
    setPost(res.data);
  };

  const fetchPosts = async () => {
    const res = await axios.get('https://jsonplaceholder.typicode.com/posts');
    await fetchPost(res.data[0].id);
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    if (id) {
      await fetchPost(id);
    } else {
      await fetchPosts();
    }
  };

  return (
    <div className="App">
      <form onSubmit={onSubmit}>
        <input type="text" onChange={(e) => {
          setId(e.target.value);
        }} />
        <button type="submit">submit</button>
      </form>
    </div>
  );
}

I hop I've helped you.

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