When to use Global State (Zustand) vs Local State in React ?
Here are the key principles to help you decide which variables belong in a Zustand store:
Put in Zustand Store:
- Shared State
- Data needed by multiple components
- State that needs to persist across route changes
- User authentication/session info
const useAuthStore = create((set) => ({
user: null,
isAuthenticated: false,
login: (userData) => set({ user: userData, isAuthenticated: true }),
logout: () => set({ user: null, isAuthenticated: false })
}));
- Global App Settings
- Theme preferences
- Language/localization settings
- Feature flags
const useSettingsStore = create((set) => ({
theme: 'light',
language: 'en',
toggleTheme: () => set((state) => ({
theme: state.theme === 'light' ? 'dark' : 'light'
}))
}));
- Cached Data
- API responses that need to be reused
- Data that's expensive to fetch
const useDataStore = create((set) => ({
products: [],
lastFetched: null,
setProducts: (products) => set({
products,
lastFetched: new Date()
})
}));
Keep in Local State (useState):
- UI State
- Form input values
- Loading states
- Modal open/close states
const [isLoading, setIsLoading] = useState(false);
const [formData, setFormData] = useState({});
- Component-Specific State
- Temporary data that only affects one component
- State that resets when component unmounts
const [isExpanded, setIsExpanded] = useState(false);
const [selectedItem, setSelectedItem] = useState(null);
- Ephemeral State
- Search input values
- Filter selections that don't need to persist
const [searchQuery, setSearchQuery] = useState('');
const [activeFilter, setActiveFilter] = useState('all');
Example Decision Process:
// ❌ Don't put in Zustand - Component specific
const [isMenuOpen, setIsMenuOpen] = useState(false);
// ✅ Put in Zustand - Needed across components
const useCartStore = create((set) => ({
items: [],
addItem: (item) => set((state) => ({
items: [...state.items, item]
}))
}));
// ❌ Don't put in Zustand - Temporary form state
const [formValues, setFormValues] = useState({
name: '',
email: ''
});
// ✅ Put in Zustand - User preferences that persist
const usePreferencesStore = create((set) => ({
notifications: true,
emailFrequency: 'daily',
updatePreferences: (prefs) => set(prefs)
}));
Key Questions to Ask:
- Does this state need to be shared between components?
- Does this state need to persist across page refreshes/navigation?
- Would multiple components benefit from accessing this state?
- Is this state temporary or permanent?
- Is the state specific to a single component's UI?
If you answer "yes" to questions 1-3, it's likely a good candidate for Zustand. If you answer "yes" to questions 4-5, it probably belongs in local state.
Remember: Don't over-globalize state. Start with local state and move to Zustand only when you have a clear need for global state management.