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

214
Vistas
How to avoid component update caused by useSelector hook

In my Table component I'm getting data from redux store with useSelector hook.

const info = useSelector(state => {
        if (type === 'catalog') {
            return store.getState().catalog.products
        }
        if (type === 'category') {
            return store.getState().categories.categories
        }
    }) 

Then I'm processing data to correct type

React.useEffect(() => {
      if(info.length) {
              const prods:any = []
              info.forEach((product: any) => {
                  const productObj: any = {}
                  productObj._prodid = product?._id
                  productObj.image = product?.catalogProduct?.image
                  productObj.category = product?.catalogProduct?.category.name
                  productObj.name = product?.catalogProduct?.name
                  productObj.pricePerPiece = product?.catalogProduct?.pricePerPiece
                  productObj.pricePerPackage = product?.catalogProduct?.pricePerPackage
                  productObj.address = product?.address
                  productObj.piecesAtStorage = product?.piecesAtStorage

                  prods.push(productObj)
              })

              setData(prods)
      }
    }, [info])

It takes 3 re-renders.

First rerender - initial data of useState

Second rerender - initial data from useSelector

Third rerender - set data from useSelector into useState

And the output looks like this.

enter image description here

Is it possible to avoid rerender caused by useSelector?

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

0

You could combine the 2 things in one selector:

const { Provider, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { createSelector } = Reselect;

const initialState = {
  catalog: {
    products: [{ _id: 1 }, { _id: 2 }],
    categories: [{ _id: 3 }, { _id: 4 }],
  },
};
const reducer = (state) => {
  return state;
};
//selectors
const selectCatalog = (state) => state.catalog;
//select product or categories and map them
const selectData = createSelector(
  [selectCatalog, (_, type) => type],
  (catalog, type) => {
    const data =
      type === 'catalog'
        ? catalog.products
        : type === 'category'
        ? catalog.categories
        : [];
    //use map instead of forEach
    return data.map((item) => ({
      //SO snippet has old babel so removed optional chaining
      //  you can put it back in your code
      _prodid: item._id,
      //you can figure out the other props
    }));
  }
);
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(
      () => (next) => (action) => next(action)
    )
  )
);
const App = () => {
  const [type, setType] = React.useState('catalog');
  const data = useSelector((state) =>
    selectData(state, type)
  );
  console.log('render app', type);
  return (
    <div>
      <select
        value={type}
        onChange={(e) => setType(e.target.value)}
      >
        <option value="catalog">catalog</option>
        <option value="category">category</option>
      </select>
      <pre>{JSON.stringify(data, undefined, 2)}</pre>
    </div>
  );
};

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>

<div id="root"></div>

about 4 years ago · Juan Pablo Isaza Denunciar

0

Have you tried shallowEqual function?

import { shallowEqual, useSelector } from 'react-redux'

const selectedData = useSelector(selectorReturningObject, shallowEqual)

The problem is it returns a new array each time it runs. As for object and array, those with same properties/values are technically not same. This is why you are seeing same empty array twice.

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