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

140
Vistas
React "magically" updates two states instead of one

I have two states defined like so:

  const [productProperties, setProductProperties] = useState<
    PropertyGroup[] | null
  >(null);
  const [originalProductProperties, setOriginalProductProperties] = useState<
    PropertyGroup[] | null
  >(null);

The first one is supposed to be updated through user input and the second one is used later for a comparison so that only the PropertyGroup's that have changed values will be submitted via API to be updated.

I have done this a thousand times before, but for some reason when I change the name value for a PropertyGroup and update the state for 'productProperties' like so:

  (e, itemId) => {
    const update = [...productProperties];
    const i = update.findIndex((group) => group.id === itemId);
    if (i !== -1) {
      update[i].name = {
        ...update[i].name,
        [selectedLocale]: e.currentTarget.value,
      };
      setProductProperties([...update]);
    }
  }

The state of originalProductProperties also updates. Why? setOriginalProductProperties is never called here, I am also not mutating any state directly and I use the spread operator to be sure to create new references. I am lost.

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

0

Preface: It sounds like the two arrays are sharing the same objects. That's fine provided you handle updates correctly.

Although you're copying the array, you're modifying the object in the array directly. That's breaking the main rule of state: Do Not Modify State Directly

Instead, make a copy of the object as well:

(e, itemId) => {
    const update = [...productProperties];
    const i = update.findIndex((group) => group.id === itemId);
    if (i !== -1) {
        update[i] = { // *** Note making a new object
            ...update[i],
            [selectedLocale]: e.currentTarget.value,
        };;
        setProductProperties(update); // (No need to *re*copy the array here, you've already done it at the top of the function)
    }
}

Or, since you have that i !== -1 check there, we could copy the array later so we don't copy it if we don't find the group matching itemId:

(e, itemId) => {
    const i = productProperties.findIndex((group) => group.id === itemId);
    if (i !== -1) {
        const update = [...productProperties];
        update[i] = { // *** Note making a new object
            ...update[i],
            [selectedLocale]: e.currentTarget.value,
        };;
        setProductProperties(update);
    }
}

FWIW, in cases where you know there will be a match, map is good for this (but probably not in this case, since you seem to indicate the group may not be there):

(e, itemId) => {
    const update = productProperties.map((group) => {
        if (group.id === itemId) {
            // It's the one we want, create the replacement
            group = {
                ...group,
                [selectedLocale]: e.currentTarget.value,
            };
        }
        return group;
    });
    setProductProperties(update);
}

Or sometimes you see it written with a conditional operator:

(e, itemId) => {
    const update = productProperties.map((group) =>
        group.id === itemId
            ? { // It's the one we want, create a replacement
                ...group,
                [selectedLocale]: e.currentTarget.value,
            }
            : group
    );
    setProductProperties(update);
}
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