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

257
Vistas
Passing array to useEffect dependency list

There's some data coming from long polling every 5 seconds and I would like my component to dispatch an action every time one item of an array (or the array length itself) changes. How do I prevent useEffect from getting into infinity loop when passing an array as dependency to useEffect but still manage to dispatch some action if any value changes?

useEffect(() => {
  console.log(outcomes)
}, [outcomes])

where outcomes is an array of IDs, like [123, 234, 3212]. The items in array might be replaced or deleted, so the total length of the array might - but don't have to - stay the same, so passing outcomes.length as dependency is not the case.

outcomes comes from reselect's custom selector:

const getOutcomes = createSelector(
  someData,
  data => data.map(({ outcomeId }) => outcomeId)
)
over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

You can pass JSON.stringify(outcomes) as the dependency list:

Read more here

useEffect(() => {
  console.log(outcomes)
}, [JSON.stringify(outcomes)])
over 4 years ago · Santiago Trujillo Denunciar

0

Another ES6 option would be to use template literals to make it a string. Similar to JSON.stringify(), except the result won't be wrapped in []

useEffect(() => {
  console.log(outcomes)
}, [`${outcomes}`])

Another option, if the array size doesn't change, would be to spread it in:

useEffect(() => {
  console.log(outcomes)
}, [ ...outcomes ])
over 4 years ago · Santiago Trujillo Denunciar

0

Using JSON.stringify() or any deep comparison methods may be inefficient, if you know ahead the shape of the object, you can write your own effect hook that triggers the callback based on the result of your custom equality function.

useEffect works by checking if each value in the dependency array is the same instance with the one in the previous render and executes the callback if one of them is not. So we just need to keep the instance of the data we're interested in using useRef and only assign a new one if the custom equality check return false to trigger the effect.

function arrayEqual(a1: any[], a2: any[]) {
  if (a1.length !== a2.length) return false;
  for (let i = 0; i < a1.length; i++) {
    if (a1[i] !== a2[i]) {
      return false;
    }
  }
  return true;
}

type MaybeCleanUpFn = void | (() => void);

function useNumberArrayEffect(cb: () => MaybeCleanUpFn, deps: number[]) {
  const ref = useRef<number[]>(deps);

  if (!arrayEqual(deps, ref.current)) {
    ref.current = deps;
  }

  useEffect(cb, [ref.current]);
}

Usage

function Child({ arr }: { arr: number[] }) {
  useNumberArrayEffect(() => {
    console.log("run effect", JSON.stringify(arr));
  }, arr);

  return <pre>{JSON.stringify(arr)}</pre>;
}

Taking one step further, we can also reuse the hook by creating an effect hook that accepts a custom equality function.

type MaybeCleanUpFn = void | (() => void);
type EqualityFn = (a: DependencyList, b: DependencyList) => boolean;

function useCustomEffect(
  cb: () => MaybeCleanUpFn,
  deps: DependencyList,
  equal?: EqualityFn
) {
  const ref = useRef<DependencyList>(deps);

  if (!equal || !equal(deps, ref.current)) {
    ref.current = deps;
  }

  useEffect(cb, [ref.current]);
}

Usage

useCustomEffect(
  () => {
    console.log("run custom effect", JSON.stringify(arr));
  },
  [arr],
  (a, b) => arrayEqual(a[0], b[0])
);

Live Demo

Edit 59467758/passing-array-to-useeffect-dependency-list

over 4 years ago · Santiago Trujillo 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