Estoy tratando de entender cuándo es necesario usar una función de igualdad personalizada en useSelector() .
Tengo un selector que devuelve un objeto simple como:
const data = useSelector(state => state.data) // => { a: "foo", b: "bar } Pensé que, dado que data son un objeto, necesitaba usar una función de igualdad personalizada para evitar una nueva representación innecesaria, como se indica en el documento :
Con useSelector(), devolver un objeto nuevo cada vez forzará una nueva representación de forma predeterminada.
Pero luego me di cuenta de que mi componente solo se volvía a renderizar cuando cambiaban data . Supuse que tal vez la función de igualdad predeterminada funciona con objetos, pero para asegurarme traté de usar una función personalizada:
const data = useSelector(state => state.data, (a, b) => a === b)); Si data no cambiaron, siempre devolverá true .
En Javascript, si trato de comparar dos objetos con === devolverá false porque las referencias son diferentes. Pero aquí con useSelector() , dado que devuelve true , significa que las referencias son las mismas.
Ahora, no estoy seguro si entendí mal el documento, pero me pregunto cuándo debo usar una función de igualdad personalizada como isEqual of Lodash.
Estoy usando Redux Toolkit, si hace alguna diferencia. Aquí hay un CodeSandox si quieres probar.
Rara vez debería necesitar escribir una función de igualdad personalizada para useSelector .
La mayoría de sus llamadas a useSelector deben ser un simple const item = useSelector(state => state.slice.item) , o pasar en una función de selector memorizada existente como const someData = useSelector(selectSomeData) .
Si necesita pasar una función de igualdad personalizada, la más común sería la función de shallowEqual exportada desde React-Redux.
Si cree que necesita usar una verificación de igualdad profunda como _.isEqual , probablemente debería hacer una pausa y reconsiderar por qué cree que necesita una verificación de igualdad profunda, porque eso normalmente no debería ser necesario en una aplicación Redux.
Además, creo que hay un pequeño malentendido aquí. Sí, state.data es un objeto, pero es una referencia a un objeto en la memoria. Cuando su reductor se actualice, RTK+Immer creará automáticamente una nueva referencia de objeto y, por lo tanto, oldObject === newObject será false porque dos objetos diferentes nunca son === entre sí. Es por eso que useSelector ya usa una comparación === por defecto: las actualizaciones inmutables significan que la comparación es realmente rápida y simple de hacer.