Perguntas de entrevista sobre Zustand 2026: Gerenciamento de estado React e melhores práticas
Prepare suas entrevistas técnicas com este guia completo sobre Zustand. Descubra perguntas frequentes, padrões de middleware, comparação com Context API e melhores práticas TypeScript.

Zustand se tornou a biblioteca de gerenciamento de estado preferida para aplicações React que precisam de mais do que a Context API, mas menos cerimônia do que o Redux. Com sua API minimalista e design TypeScript-first, perguntas sobre Zustand aparecem regularmente em entrevistas frontend, particularmente para posições React de nível intermediário e sênior.
As perguntas de entrevista sobre Zustand avaliam três áreas: compreensão do padrão store versus o estado nativo do React, conhecimento de quando o Zustand supera as alternativas, e capacidade de estruturar stores para manutenibilidade.
Conceitos fundamentais do Zustand que todo candidato deve conhecer
Zustand v5, lançado no final de 2024, introduziu várias mudanças importantes em relação à v4. A função create não requer mais uma chamada separada ao useStore, e o middleware persist agora usa um modelo de hidratação síncrona por padrão. Os entrevistadores esperam que os candidatos conheçam a API atual.
O que torna o Zustand diferente de useState e useReducer?
As stores do Zustand existem fora da árvore de componentes React. Essa diferença arquitetural tem três consequências práticas:
- O estado persiste entre montagens e desmontagens de componentes sem providers de Context
- Atualizações não disparam re-renderizações em componentes pai, apenas componentes inscritos se re-renderizam
- O estado pode ser acessado sincronamente fora do React, útil para handlers de eventos e lógica assíncrona
import { create } from 'zustand'
interface CartStore {
items: CartItem[]
addItem: (item: CartItem) => void
clearCart: () => void
totalPrice: () => number
}
export const useCartStore = create<CartStore>((set, get) => ({
items: [],
addItem: (item) => set((state) => ({
items: [...state.items, item]
})),
clearCart: () => set({ items: [] }),
totalPrice: () => get().items.reduce((sum, item) => sum + item.price, 0)
}))A função get fornece acesso síncrono ao estado atual, evitando o problema de closure obsoleta comum com useState.
Como o Zustand lida com re-renderizações?
O Zustand usa igualdade superficial por padrão. Quando um componente se inscreve em uma store com useCartStore(), ele recebe o objeto de estado completo e se re-renderiza em qualquer mudança. Selecionar slices específicos previne renderizações desnecessárias:
// Ruim: re-renderiza em qualquer mudança na store
const { items } = useCartStore()
// Bom: re-renderiza apenas quando items muda
const items = useCartStore((state) => state.items)
// Múltiplos valores: usar comparação superficial
import { shallow } from 'zustand/shallow'
const { items, totalPrice } = useCartStore(
(state) => ({ items: state.items, totalPrice: state.totalPrice() }),
shallow
)O comparador shallow de zustand/shallow realiza igualdade de referência nas propriedades do objeto em vez do objeto em si.
Zustand vs Context API: quando escolher cada um
Essa pergunta de comparação aparece em quase todas as entrevistas que cobrem gerenciamento de estado. A resposta depende da frequência de atualizações e da complexidade do estado.
| Critério | Context API | Zustand |
|---|---|---|
| Tamanho do bundle | 0 KB (integrado) | 1.2 KB gzipped |
| Controle de re-renders | Manual com memo/useMemo | Seletores integrados |
| DevTools | Apenas React DevTools | Compatível com Redux DevTools |
| Server Components | Suporte completo | Requer boundary cliente |
| Estado assíncrono | Requer wrapper | Suporte nativo |
A Context API funciona bem para valores que mudam pouco frequentemente como tema ou locale. O Zustand se destaca quando atualizações de estado ocorrem frequentemente, como inputs de formulário, dados em tempo real ou carrinhos de compra. A documentação do React sobre gerenciamento de estado recomenda elevar o estado e usar Context para problemas de "prop drilling", enquanto stores externos são adequados para padrões de atualização complexos.
As stores do Zustand requerem a diretiva "use client". Para aplicações que usam React Server Components extensivamente, isso significa que o estado do Zustand vive apenas em componentes cliente. Arquiteturas híbridas frequentemente passam dados obtidos do servidor como props para componentes cliente que então sincronizam com o Zustand.
Padrões de middleware no Zustand
As perguntas sobre middleware testam se um candidato entende composição sobre configuração. Os middlewares do Zustand envolvem a função criadora da store, adicionando comportamento sem modificar a API principal.
Como o middleware persist funciona?
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
interface UserPreferences {
theme: 'light' | 'dark'
language: string
setTheme: (theme: 'light' | 'dark') => void
}
export const usePreferencesStore = create<UserPreferences>()(
persist(
(set) => ({
theme: 'light',
language: 'en',
setTheme: (theme) => set({ theme })
}),
{
name: 'user-preferences',
storage: createJSONStorage(() => localStorage),
partialize: (state) => ({ theme: state.theme, language: state.language })
}
)
)A opção partialize exclui funções e estado derivado da persistência. Sem ela, a serialização falha ou o armazenamento fica inchado com dados desnecessários. A documentação do Zustand sobre persist cobre estratégias de migração para mudanças de schema.
Combinando múltiplos middleware
Os middlewares se compõem de dentro para fora. O middleware mais interno executa primeiro:
import { create } from 'zustand'
import { devtools, persist, subscribeWithSelector } from 'zustand/middleware'
import { immer } from 'zustand/middleware/immer'
export const useStore = create<StoreState>()(
devtools(
persist(
subscribeWithSelector(
immer((set) => ({
// state and actions
}))
),
{ name: 'app-storage' }
),
{ name: 'AppStore' }
)
)O middleware immer permite atualizações de estilo mutável que produzem estado imutável. O middleware subscribeWithSelector permite se inscrever em slices de estado fora dos componentes React.
Pronto para mandar bem nas entrevistas de React / Next.js?
Pratique com nossos simuladores interativos, flashcards e testes tecnicos.
Padrões de integração com TypeScript
O Zustand v5 melhorou significativamente a inferência TypeScript. O padrão de dupla chamada de função create<Type>()() fornece inferência de tipos completa para cadeias de middleware.
Tipando ações que referenciam outro estado
interface TodoStore {
todos: Todo[]
filter: 'all' | 'active' | 'completed'
addTodo: (text: string) => void
toggleTodo: (id: string) => void
filteredTodos: () => Todo[]
}
export const useTodoStore = create<TodoStore>()((set, get) => ({
todos: [],
filter: 'all',
addTodo: (text) => set((state) => ({
todos: [...state.todos, { id: crypto.randomUUID(), text, completed: false }]
})),
toggleTodo: (id) => set((state) => ({
todos: state.todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
})),
filteredTodos: () => {
const { todos, filter } = get()
switch (filter) {
case 'active': return todos.filter((t) => !t.completed)
case 'completed': return todos.filter((t) => t.completed)
default: return todos
}
}
}))Estado derivado como funções em vez de getters evita valores obsoletos. Cada chamada a filteredTodos() lê o estado atual.
Dividindo stores para aplicações grandes
Uma pergunta comum de entrevista pergunta como estruturar o Zustand para escalar. O padrão slice divide uma store em módulos por domínio:
import { StateCreator } from 'zustand'
export interface AuthSlice {
user: User | null
isAuthenticated: boolean
login: (credentials: Credentials) => Promise<void>
logout: () => void
}
export const createAuthSlice: StateCreator<
AuthSlice & CartSlice, // Tipo da store combinada
[],
[],
AuthSlice
> = (set) => ({
user: null,
isAuthenticated: false,
login: async (credentials) => {
const user = await authApi.login(credentials)
set({ user, isAuthenticated: true })
},
logout: () => set({ user: null, isAuthenticated: false })
})import { create } from 'zustand'
import { createAuthSlice, AuthSlice } from './slices/authSlice'
import { createCartSlice, CartSlice } from './slices/cartSlice'
export const useStore = create<AuthSlice & CartSlice>()((...args) => ({
...createAuthSlice(...args),
...createCartSlice(...args)
}))Os slices podem referenciar uns aos outros através do tipo de store combinada passado para StateCreator.
Perguntas comuns de entrevista com respostas modelo
Quando o Zustand seria uma má escolha?
O Zustand adiciona complexidade sem benefício nestes cenários:
- Dados de configuração estática que nunca mudam em tempo de execução
- Estado de formulário gerenciado por React Hook Form ou bibliotecas similares
- Estado do servidor melhor gerenciado por TanStack Query ou SWR
- Passagem de props simples pai-filho com 2-3 níveis de aninhamento
A seção de comparação do repositório GitHub do Zustand fornece a perspectiva dos mantenedores sobre as alternativas.
Como testar componentes que usam Zustand?
Os testes requerem resetar o estado da store entre testes e opcionalmente mockar a store completamente:
import { act, renderHook } from '@testing-library/react'
import { useCartStore } from './store'
beforeEach(() => {
// Resetar a store para o estado inicial
useCartStore.setState({ items: [], totalItems: 0 })
})
test('addItem increases cart count', () => {
const { result } = renderHook(() => useCartStore())
act(() => {
result.current.addItem({ id: '1', name: 'Product', price: 10 })
})
expect(result.current.items).toHaveLength(1)
})Para testes de componentes que não devem interagir com stores reais, mockar no nível do módulo:
import { vi } from 'vitest'
vi.mock('./store', () => ({
useCartStore: vi.fn(() => ({
items: [{ id: '1', name: 'Mock Product', price: 25 }],
addItem: vi.fn()
}))
}))Como o Zustand lida com operações assíncronas?
Diferente do Redux, o Zustand não tem requisito de middleware para async. As ações podem ser funções assíncronas diretamente:
interface ProductStore {
products: Product[]
isLoading: boolean
error: string | null
fetchProducts: () => Promise<void>
}
export const useProductStore = create<ProductStore>((set) => ({
products: [],
isLoading: false,
error: null,
fetchProducts: async () => {
set({ isLoading: true, error: null })
try {
const products = await productApi.getAll()
set({ products, isLoading: false })
} catch (err) {
set({ error: err.message, isLoading: false })
}
}
}))Para fluxos assíncronos complexos, o guia de padrões async do Zustand recomenda manter os estados de loading e error colocalizados com os dados que descrevem.
Mudanças do Zustand v5 que podem aparecer em entrevistas
O Zustand v5 introduziu mudanças importantes que os entrevistadores usam para avaliar se os candidatos se mantêm atualizados:
- Sem mais exports padrão: Importar
{ create }em vez decreate - TypeScript mais rigoroso: O padrão
create<T>()()substituicreate<T>() - Hidratação persist síncrona: O timing do callback
onRehydrateStoragemudou - Abandono do suporte CJS: Pacote apenas ESM
Migrar da v4 para a v5 requer atualizar as declarações de importação e ajustar qualquer código que dependia do timing de hidratação anterior.
Pontos-chave para entrevistas sobre Zustand
- As stores do Zustand vivem fora da árvore React, permitindo acesso síncrono e prevenindo aninhamento de providers
- Seletores com comparação superficial otimizam re-renders para aplicações em produção
- O middleware persist requer
partializepara excluir funções do armazenamento - O padrão slice escala o Zustand para aplicações grandes sem sacrificar a segurança de tipos
- Ações async funcionam diretamente sem middleware, diferente dos padrões Redux
- Os testes requerem reset explícito do estado entre casos de teste
- Server Components forçam o Zustand para boundaries cliente, influenciando decisões de arquitetura
Comece a praticar!
Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.
Você saberia encontrar o bug em React / Next.js?
Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Escrito por
Anthony Fillion-MailletFundador da SharpSkill
Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.
Atualizado em 25 de agosto de 2026
Tags
Compartilhar
Artigos relacionados

React 19 Suspense e Renderização Concorrente: Streaming SSR e Perguntas de Entrevista 2026
Guia completo sobre React 19 Suspense, renderização concorrente e Streaming SSR. Padrões avançados e preparação para entrevistas técnicas em 2026.

React Compiler em 2026: memoização automática e perguntas de entrevista
Análise completa do React Compiler em 2026: pipeline de compilação, memoização automática, regras do React e perguntas frequentes em entrevistas técnicas.

Server Actions no Next.js 16 em 2026: Mutações, Revalidação e Perguntas de Entrevista
Como as Server Actions do Next.js 16 lidam com mutações, revalidação, estado de pendência, UI otimista e segurança, com as perguntas de entrevista que testam cada conceito.