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

185
Visualizações
How to fetch up-to-date data inside async?

I have a function which fetches data.

const fetchData = async (filter) => {
  if (loading) return

  loading = true
  const data = await api(filter)
  setData(data)
  loading = false
}

I also have a filter component, when I change filters it calls my fetchData() function with the new filter variable.

This all works, however there is an issue

This issue occurs when I switch my filter but my fetching function is in a loading state. This causes the if check to fail and I now see outdated data because a re-fetch never happens.

My initial idea was to create a const q = [] variable, and inside if (loading) i would push my filters, and somehow at the end I would re-fetch with the last element inside my q array and then clear that array.

I dont really know how to do that re-fetch logic. A setInterval(() => checkQ(), 1000)? Doesn't seem right

What would be a better approach to take?

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

You should use an AbortController - that's part of the fetch, as my experience tells me that it's not hard to initiate a new fetch request, but what to do with the first request, when you send out a second?

Here's a snippet that will do the thing you asked - but also deals with the unnecessary requests:

const { useState, useEffect } = React

const useFetchData = () => {
  const [users, setUsers] = useState([])
  
  let controller = null
  
  const fetchData = () => {
    console.log('fetch initiated')
    if (controller) controller.abort()
    controller = new AbortController();
    const { signal } = controller;
    fetch('https://jsonplaceholder.typicode.com/users', { signal })
      .then(response => {
        console.log('request response')
        return response.json()
      })
      .then(json => {
        console.log('retrieved list:', json)
        setUsers(() => json || [])
      })
      .catch(err => {
        if(err.name === "AbortError") {
          console.warn('Abort error', err)
        }
      })
  }
  
  return { fetchData }
}

const FetchData = () => {
  const { fetchData } = useFetchData()
  
  return (
    <div>
      <button onClick={fetchData}>FETCH DATA</button><br />
    </div>
  )
}

const FetchAbortFetchData = () => {
  const { fetchData } = useFetchData()
  
  return (
    <div>
      <button onClick={() => {
        fetchData()
        fetchData()
      }}>FETCH-ABORT-FETCH DATA</button><br />
    </div>
  )
}

const App = () => {
  return (
    <div>
      <FetchData /><br />
      <FetchAbortFetchData />
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>

<div id="root"></div>

about 4 years ago · Juan Pablo Isaza Relatório

0

Easiest way is to use your filter criteria as the lock.

Advantages

  1. Always fetching data immediately
  2. Only calling setData with the results from the most recent filter criteria
  3. Simple

Disadvantages

  1. May have multiple simultaneous requests
  2. Toggling back/forth between filters may lead to a race condition.
let latestFilter = null;

const fetchData = async (filter) => {
  // Check to see if its there's the same request already in progress
  // Note: may need to deep equal to check the filter
  if (filter === latestFilter) return;

  // Set the current request as most up to date
  latestFilter = filter

  // Fetch Data (async)
  const data = await api(filter)

  // If the filter is still the most up to date, use it. Otherwise discard.
  // Note: may need to deep equal to check the filter
  if (filter === latestFilter) {
    setData(data)
    latestFilter = null
  }
}

In order to solve disadvantage 2, you can include a counter. This will ensure that only the most recent request will run setData.

let latestFilter = null;
let latestRequestNumber = 0

const fetchData = async (filter) => {
  if (filter === latestFilter) return;
  latestFilter = filter

  // Identify the current request
  const requestNumber = latestRequestNumber + 1;
  // Store this number
  latestRequestNumber = requestNumber

  const data = await api(filter)

  // Update data only if we are the most recent request. 
  if (callCount = latestCallCount) {
    setData(data)
    latestFilter = null
  }
}
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