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

143
Vistas
Ignore previous callback result if state has changed in the meantime

I have page displaying a list of countries provided by an external library. When I click on a country, it shows me all cities in it.
Each country object has a method to get the list of cities in it, provided by the library.
I have a CountryComponent like this

import { City, Country } from "an-external-library";

export const CountryComponent: FC<Props> = ({ country: Country }) => {
  const [cities, setCities] = useState<City[]>([]);

  useEffect(() => {
    country
      .getCities()
      .then(setCities)
      .catch(console.error);
  }, [country]);

// ...
}

I want to get cities every time the component mounts and also if the country changes.
The problem is that if I keep changing the country quickly, it will call getCities() every time I click on a country on the list. Since there's no way of knowing in which order the responses to those calls will arrive, in the end cities will be the response that arrived last, whatever it is.
This means I may end up with country: France; cities: New York, Los Angeles, etc...


Solutions I've tried

  • Unmounting CountryComponent and mounting again if country changes.

In the parent component, I have

const handleChangeCountry = (c: Country) => {
  setCountry(undefined);
  setTimeout(() => setCountry(c), 10);
}

render (
  <>
    <CountryList onCountryClick={handleChangeCountry}/>
    {country ?
      <CountryComponent country={country}/>
    :
      <Spinner />
    })
  </>
)

This a solution so ugly that just writing this gives me the creeps.
But it worked. Just that I couldn't get the UI to look clean when the CountryComponent disappeared for 10 ms and appeared again; and want a better solution.


Solutions I haven't tried

As suggested by @chimera, debouncing could be a solution.
While searching for solutions before posting, I found this answer, but didn't try it because I believe that it would cause the list of cities to take a while to respond to clicks on countries, and that's not ideal either.


Ideally, I would like to ignore all callbacks from getCities() except the last, but I don't know how I'd achieve this.

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

0

This is a typical issue: you get unordered asynchronous responses, potentially overwriting the most recent (and the only relevant) state.

A very easy solution is to use react-use's useAsync hook, which includes several useful mechanisms for this typical issue, the one interesting here being that it discards the responses of every previous requests, keeping only the response to the most recent request.

React hook that resolves an async function or a function that returns a promise;

import { useAsync } from "react-use";

const CountryComponent = ({ country: Country }) => {
  // With react-use's useAsync,
  // no need for separate state and useEffect
  const cities = useAsync(
    () => country.getCities(),
    [country]
  ).value; // returned object { loading: boolean, value: T, error }
  
  // ...
}
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