Search code examples
javascriptreduxreact-redux

Redux 5 - Selectors that return a new reference (such as an object or an array) should be memoized warning occurs with filter array method


I am a beginner Redux learner. I have a React 18 app. I am using redux 5 and react-redux 9.

When I run my application I get the below warning in my browser:

AnecdoteList.jsx:14 Selector unknown returned a different result when called with the same parameters. This can lead to unnecessary rerenders. Selectors that return a new reference (such as an object or an array) should be memoized

Warning image:

Redux 5 selector unknown warning

The link in the warning leads to Optimizing Selectors with Memoization.

My AnecdoteList.jsx file below:

import { useDispatch, useSelector } from 'react-redux';
import { increaseVotes } from '../reducers/anecdoteReducer';

const AnecdoteList = () => {
  const compareAnecdotes = (a, b) => {
    if (a.votes < b.votes) return 1;
    if (a.votes > b.votes) return -1;
    return 0;
  };

  const dispatch = useDispatch();

  // THIS IS CAUSING THE WARNING
  const anecdotes = useSelector(({anecdotes, filter}) => {
    return anecdotes
      .filter(a => a.content.includes(filter))
      .sort(compareAnecdotes);
  });

  return (
    <div>
      {anecdotes.map((anecdote) => (
        <div key={anecdote.id}>
          <div>{anecdote.content}</div>
          <div>
            has {anecdote.votes}
            <button onClick={() => dispatch(increaseVotes(anecdote.id))}>
              vote
            </button>
          </div>
        </div>
      ))}
    </div>
  );
}

export default AnecdoteList;

The useSelector hook seems to be causing the warning. I believe it is the filter array method, but I am not sure. How should I memoize this? What am I doing wrong here and how can I fix this?


Solution

  • @Drew Reese pointed me to this solution How Exactly useselector works?

    Below are the updates I made in the code:

    import { useDispatch, useSelector, shallowEqual } from 'react-redux'; // added the import for shallowEqual
    import { increaseVotes } from '../reducers/anecdoteReducer';
    
    const AnecdoteList = () => {
      ...
    
      const anecdotes = useSelector(({anecdotes, filter}) => {
        return anecdotes
          .filter(a => a.content.includes(filter))
          .sort(compareAnecdotes);
      }, shallowEqual); // added the second parameter to useSelector
    
      return ( ... );
    }
    
    export default AnecdoteList;
    

    Adding the shallowEqual removed the warning from the console.