'useSelector with argument causes Maximum update depth exceeded

I currently have this selector:

export const getTasksForProjectSelector = (state, projectSlug) => state.task.tasks.filter((task) => task.project.slug === projectSlug);

which should filter for tasks that belong to a certain project. I'm calling the selector with

  const tasks = useSelector((state) => getTasksForProjectSelector(state, projectSlug));

but this causes a Warning: Maximum update depth exceeded error. I've also tried to rewrite the selector like:

export const getTasksForProjectSelector = (projectSlug) => (state) => state.task.tasks.filter((task) => task.project.slug === projectSlug);

but the same error appears. I'm sure that the error is becase of the selector because when I call an ordinary selector (without passing an argument) to get all tasks such as (state) => state.task.tasks, everything works as it should



Solution 1:[1]

Your selector creates a new array on every invocation, so lastValue !== newValue will always be true and always cause a rerender.

For something like this, you need to use a memoized selector, e.g. with reselect:

export const getTasksForProjectSelector = createSelector(
  state => state.task.tasks
  (state, projectSlug) => projectSlug,
  (tasks, projectSlug) => 
    tasks.filter((task) => task.project.slug === projectSlug)
)

I'd recommend reading up the Redux docs on derived data

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 phry