Skip to main content
When you need to subscribe to a computed state from a store, the recommended way is to use a selector. However, the computed selector will cause a re-render if the output has changed according to Object.is. In cases where the computed value is always shallow equal to the previous one, you can use useShallow to avoid unnecessary re-renders.

The Problem

Consider a store that associates each bear with a meal:
import { create } from 'zustand'

const useMeals = create(() => ({
  papaBear: 'large porridge-pot',
  mamaBear: 'middle-size porridge pot',
  littleBear: 'A little, small, wee pot',
}))

export const BearNames = () => {
  const names = useMeals((state) => Object.keys(state))

  return <div>{names.join(', ')}</div>
}
Now when papa bear wants a pizza instead:
useMeals.setState({
  papaBear: 'a large pizza',
})
This change causes BearNames to re-render even though the actual output of names has not changed according to shallow equality. The array ['papaBear', 'mamaBear', 'littleBear'] is recreated with a new reference each time.

The Solution: useShallow

Wrap your selector with useShallow to compare the result using shallow equality:
import { create } from 'zustand'
import { useShallow } from 'zustand/react/shallow'

const useMeals = create(() => ({
  papaBear: 'large porridge-pot',
  mamaBear: 'middle-size porridge pot',
  littleBear: 'A little, small, wee pot',
}))

export const BearNames = () => {
  const names = useMeals(useShallow((state) => Object.keys(state)))

  return <div>{names.join(', ')}</div>
}
Now the bears can all order different meals without causing unnecessary re-renders of the BearNames component. The component only re-renders when the keys actually change.

When to Use useShallow

Use useShallow

  • Selecting arrays of values
  • Selecting objects with multiple properties
  • Any computed value that returns a new reference but with shallow-equal contents

Skip useShallow

  • Selecting primitive values (strings, numbers, booleans)
  • Selecting single object references
  • When you need deep equality checks

Common Use Cases

// Without useShallow - re-renders on any state change
const items = useStore((state) => state.items.map(item => item.id))

// With useShallow - only re-renders when IDs actually change
const items = useStore(useShallow((state) => state.items.map(item => item.id)))
useShallow performs a shallow comparison of the selector result, checking if all values at the first level are equal using Object.is. This is perfect for arrays and objects with primitive values.

Build docs developers (and LLMs) love