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

295
Vistas
Reselect: createSelector not working correctly

I have a problem with my memoized selectors.

Reading the docs on https://redux.js.org/usage/deriving-data-selectors I taken this snippets:

const state = {
  a: {
    first: 5
  },
  b: 10
}

const selectA = state => state.a
const selectB = state => state.b

const selectA1 = createSelector([selectA], a => a.first)

const selectResult = createSelector([selectA1, selectB], (a1, b) => {
  console.log('Output selector running')
  return a1 + b
})

const result = selectResult(state)
// Log: "Output selector running"
console.log(result)
// 15

const secondResult = selectResult(state)
// No log output
console.log(secondResult)
// 15

My problem is that the secondResult function, log the result.

All this is a little premise.

My very problem:

  • I'am using react with @reduxjs/toolkit
  • I have a list of todo
  • I created a "todoAdapter" to manage a list as entities
  • I want to use memoized selected to update a single "todo" without re-render the entire list optimizing my app.

but...

When I dispatch an update with "adapter.updateOne", the standard selector "SelectAll" every time (i think) changes ref.

Example

I have this selectors from "slice"

export const {
    selectAll,
    selectIds: selectTodosIDs,
    selectTotal: selectTodosCount,
    selectById: selectTodoById
} = todosSelector;

If I create this selector

export const selectIdsCustom = createSelector(
    selectTodosIDs,

    (ids) => {
        console.log('execute output function');
        return ....
    }
)

It' all ok (state.todos.ids not change obviously).

If I create this selector:

export const selectTodosCustom = createSelector(
    selectAll,

    (todos) => {
        console.log('execute output function');
        return ....
    }
)

selectTodosCustom run "always".

Whyyy???

With updateOne I am modifing "only" an entity inside "state.todos.entities"

Where am I wrong ?? What I did not understand?

My app is just un case study. The complete app is on: https://codesandbox.io/s/practical-hermann-60i7i

I only created the same app in typescript and, when I as my app had this problem:

  • I download the original app form link above (official redux example)
  • npm install
  • npm start

But I have the some problem also in the official example!!!!!

Problem is my env? some library version?

Help me plese!!

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

0

When I dispatch an update with "adapter.updateOne", the standard selector "SelectAll" every time (i think) changes ref.

Yes, you are right. It is correct. selectAll from @reduxjs/toolkit depends on ids and entities from the entities state.

{
  ids: ['1', '2'],
  entities: {
    1: {
      id: '1',
      title: 'First',
    },
    2: {
      id: '2',
      title: 'Second',
    },
  },
}

Every time you dispatch an update with adapter.updateOne, the reference to the entities object changes. This is normal, this is how immerjs (used under the hood of reduxtoolkit) provides correct immutability:

dispatch(updateOne({ id: '1', changes: { title: 'First (altered)' } }));

const state = {
  ids: ['1', '2'],
  entities: { // <--- new object
    1: { // <--- new object
      id: '1',
      title: 'First (altered)',
    },
    2: { // <--- old object
      id: '2',
      title: 'Second',
    },
  },
};

If the entities object remained old, the selector selectAll would return a memoized value with an incorrect title for the first element.

To optimize the re-render of the list (which in actually useful only for large lists), you should use selector selectIds in the parent component and selector selectById in the child components.

const Child = ({ id }) => {
  const dispatch = useDispatch();
  const book = useSelector((state) => selectById(state, id));

  const handleChange = useCallback(() => {
    // the parent component will not be re-render
    dispatch(
      bookUpdate({
        id,
        changes: {
          title: `${book.title} (altered)`,
        },
      })
    );
  }, [dispatch, id, book]);

  return (
    <div>
      <h2>{book.title}</h2>
      <button onClick={handleChange}>change title</button>
    </div>
  );
};

function Parent() {
  const ids = useSelector(selectIds);

  return (
    <div>
      {ids.map((id) => (
        <Child key={id} id={id}></Child>
      ))}
    </div>
  );
}

UPDATE

In this case, item not change ref and in "entities" I am changing a single prop inside it.

It is not right???

No, you can't do that when using redux. Redux is based on the idea of immutability. Any state change creates a new state object. Updating an entity is just a deep change of the state object. And all objects on the path to the updated element must be new. If you do not follow this rule, then base tools will not work correctly. All of them use strict comparison by default.

But you can still avoid re-render the component even when the selector returns the equal arrays with different references. Just pass your own comparison function:

...  
const todoIds = useSelector(
    selectFilteredTodoIds, 
   // the component will be re-render only if this function returns false
    (next, prev) => next.every((id, index) => id === prev[index])
);
...
about 4 years ago · Juan Pablo Isaza Denunciar

0

Thanks very much Denwakeup.

If you look for the app on link, You will see that there are filters.

I can't use selectIds but I get the filtered ids from another selector based on "selectAll" and "selectFilters" My wish is:

  • If I add or remove an item... yes selectAll change ref. It is ok
  • but if i change a single entity, why change ref of entities?? I change an inner entity and not the entire entity object.

Is it possibile change only a single entity??

It is like I have:

const item = {
   name: 'X'
}

item.name = 'Y'

In this case, item not change ref and in "entities" I am changing a single prop inside it.

It is not right???

Thanks

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