O que são bibliotecas de gerenciamento de estado e quando você deve usá-las?
À medida que seu app cresce, gerenciar como os dados fluem entre os componentes pode se tornar complexo.
Ao começar, o hook
useState do React pode ser suficiente, mas à medida que você adiciona recursos, pode encontrar problemas com:
- Passar props por componentes que não precisam deles, também conhecido como prop drilling
- Manter os dados sincronizados entre diferentes partes do seu app
- Manipulando atualizações complexas que afetam múltiplos componentes simultaneamente
useState, então é perfeita para casos como alternância de tema ou status de autenticação do usuário.
No entanto, a Context API não lida bem com atualizações frequentes e pode causar re-renderizações desnecessárias, tornando-a menos adequada para necessidades complexas de estado em aplicações como eCommerce e plataformas de mídia social.
Aqui está um componente counter que demonstra o uso básico da Context API:
import { useState, createContext } from 'react';
const CounterContext = createContext();
const CounterProvider = ({ children }) => {
const [count, setCount] = useState(0);
return (
<CounterContext.Provider value={{ count, setCount }}>
{children}
</CounterContext.Provider>
);
};
export { CounterContext, CounterProvider };
Este código cria um contexto e um provider para compartilhar um estado count em toda a aplicação.
CounterProvider usa o hook useState para inicializar e gerenciar o estado count e seu setter. Ambos são então passados para componentes filhos através do Provider.
Então, quando você envolve seu aplicativo inteiro com o CounterProvider, o estado count fica disponível em toda a sua aplicação.
Veja como você pode envolver CounterProvider ao redor da sua aplicação:
import { CounterProvider } from './context/CounterContext';
function App() {
return (
<CounterProvider>
{/* App components */}
</CounterProvider>
);
}
export default App;
E aqui está como você pode usar o estado count:
import React, { useContext } from 'react';
import { CounterContext } from '../context/CounterContext';
const Counter = () => {
const { count, setCount } = useContext(CounterContext);
return (
<>
<div style={{ textAlign: 'center' }}>
<h1>Context API Counter</h1>
<button style={{ marginRight: '5px' }} onClick={() => setCount(count - 1)}>
Decrease
</button>
<span>{count}</span>
<button style={{ marginLeft: '5px' }} onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
</>
);
};
export default Counter;
Como você pode ver, o count e sua função setter, setCount, são inicializados através da função useContext.
O estado atual count é então exibido, e setCount é usado para aumentar e diminuir o estado count quando o usuário clica nos botões de decremento e incremento respectivamente.
Outra biblioteca popular de gerenciamento de estado é o Redux, que é uma das bibliotecas de gerenciamento de estado mais populares para usar com React. Está por aí há muito tempo e é ideal para aplicações maiores como eCommerce e plataformas de mídia social, fóruns e assim por diante.
Redux gerencia o estado fornecendo uma store central e controle rigoroso sobre as atualizações de estado. Ele usa um padrão previsível com actions, reducers e middleware.
Ações são cargas úteis de informação que enviam dados da sua aplicação para o Redux store, frequentemente acionadas por interações do usuário.
Reducers são funções que especificam como o estado deve mudar em resposta a essas ações, garantindo que o estado seja atualizado de forma imutável.
Middleware, por outro lado, atua como uma ponte entre o despacho de ações e o reducer, permitindo que você estenda a funcionalidade do Redux (por exemplo, logging, handling async operations) sem modificar o fluxo principal.
A reclamação mais comum sobre Redux é todo o código boilerplate que você precisa para começar. Em resposta, a equipe do Redux introduziu "Redux Toolkit" e "RTK Query", que simplificam bastante o processo de configuração.
Normalmente você define tanto as actions quanto os reducers em um único arquivo usando a função createSlice(). É comum nomear o arquivo para que termine com a palavra Slice, por exemplo, productSlice, userSlice, counterSlice e assim por diante.
Aqui está um arquivo counterSlice para mostrar o básico:
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { count: 0 },
reducers: {
increment: (state) => {
state.count += 1;
},
decrement: (state) => {
state.count -= 1;
},
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
A partir daqui, você precisa envolver todo o app com o Provider, selecionar uma parte do estado do slice com useSelector(), e então usar useDispatch() para ativar o estado.
Outra opção a considerar é Zustand.
Zustand é uma biblioteca leve de gerenciamento de estado com uma API simples. É baseado em hooks, então há menos boilerplate comparado ao Redux, tornando mais fácil e rápido de configurar.
Zustand é ideal para aplicações de pequeno a médio porte. It works by using a useStore hook to access state directly in components and pages. Isso permite que você modifique e acesse dados sem precisar de actions, reducers ou um provider.
Aqui está um useCounterStore que implementa outra funcionalidade de contador:
import { create } from 'zustand';
const useCounterStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}));
export default useCounterStore;
E aqui está como inicializar e usar os estados no seu app:
// Import the useCounterStore (it's just a hook)
import useCounterStore from '../useCounterStore';
const Counter = () => {
// Initialize the states with the useCounterStore hook
const { count, increment, decrement } = useCounterStore();
return (
<>
<div style={{ textAlign: 'center' }}>
<h1>Zustand Counter</h1>
<button style={{ marginRight: '5px' }} onClick={() => decrement()}>
Decrease
</button>
<span>{count}</span>
<button style={{ marginLeft: '5px' }} onClick={() => increment()}>
Increase
</button>
</div>
</>
);
};
export default Counter;
Embora o ecossistema de front-end esteja em constante evolução e novas bibliotecas de gerenciamento de estado surjam regularmente, as que discutimos são amplamente usadas na indústria.Este módulo não possui perguntas. Marque como concluído.