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

190
Vistas
Creating a createSelector in Redux that does not rerender unrelated components

I have a simple document maker that allows users the create multiple fields of two types (input field and label field). They can also rearrange the field via drag and drop. My data structure is based on the Redux guide on data normalization.

LIST field is input type (e.g. children id 21 and 22) - onChange will dispatch action and allows the input text to modified without re-rendering other fields.

With LABEL field we allow users to select from a dropdown list of only 3 labels (Danger, Slippery, Flammable). Selecting one with remove it from the dropdown list to prevent duplicate label. For example, if there are "Danger" and "Slippery" in the field, the dropdown field will only show one option "Flammable". To achieve this, I use createSelector to get all children and filter them base on their parent (fieldId). This gives me an array of existing labels ["Danger","Slippery"] in that fieldId. This array will then be used to filter from a fixed dropdown array of three options with useEffect.

Now whenever I update the input text, it will also re-render the LABEL field (based on the Chrome React profiler).

It does not affect performance but I feel like I am missing something with my createSelector.

Example:

export const documentSlice = createSlice({
  name: "document",
  initialState: {
    fields: {
      1: { id: 1, children: [11, 12] },
      2: { id: 2, children: [21, 22] },
    },
    children: {
      11: { id: 11, type: "LABEL", text: "Danger", fieldId: 1 },
      12: { id: 11, type: "LABEL", text: "Slippery", fieldId: 1 },
      21: { id: 21, type: "LIST", text: "", fieldId: 2 },
      22: { id: 22, type: "LIST", text: "", fieldId: 2 },
    },
    fieldOrder:[1,2]
  },
});

createSelector

export const selectAllChildren = (state) => state.document.children;
export const selectFieldId = (state, fieldId) => fieldId;

export const getChildrenByFieldId = createSelector(
  [selectAllChildren, selectFieldId],
  (children, fieldId) => {
    const filterObject = (obj, filter, filterValue) =>
      Object.keys(obj).reduce(
        (acc, val) =>
          obj[val][filter] !== filterValue ? acc : [...acc, obj[val].text],
        []
      );
    const existingChildren = filterObject(children, "fieldId", filterId);
    return existingChildren;
  }
);
about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

After more reading up, this is what finally works for me. Hopefully someone will find it useful.

  1. Given the normalized data, the object reduce function can be simplified.
slice.js 

export const getChildrenByFieldId = createSelector(
  [selectAllChildren, selectFieldId],
  (children, fieldId) => {

    // get the children from fields entry => array [11,12]
    const childrenIds = state.document.fields[fieldId].children

    let existingChildrenText = [];

    // loop through the created array [11,12] 
    childrenIds.forEach((childId) => {
      // pull data from the individual children entry
      const childText = children[childId].text;
      existingChildrenText.push(childText);
    });
    return existingChildrenText;

  }
);
  1. To prevent re-render, we can use shallowEqual comparison on the output array to compare only the values of the array.
//app.js 

import { shallowEqual, useSelector } from "react-redux";

const childrenTextData = useSelector((state) => {
  return getChildrenByFieldId(state, blockId);
}, shallowEqual);
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