useReducer
O hook useReducer
é uma alternativa ao useState
, especialmente útil quando o gerenciamento de estado se torna mais complexo. Ele é baseado no conceito de reducers, muito parecido com o que usamos no Redux.
Enquanto o useState
é mais simples para estados isolados, o useReducer
brilha quando precisamos gerenciar múltiplas transições de estado ou quando as mudanças dependem do estado anterior de uma maneira mais controlada.
Ele é altamente recomendado para evitar a criação de vários hooks com useState, o que pode poluir a página e disparar de forma demasiada re-renders na aplicação. Abaixo trago um exemplo de uso:
import { userReducer } from 'react'; // Estado inicial para configuração e controle do chat const initialState = { message: '', chatHistory: [], modelConfig: { temperature: 0.7, top_k: 50, top_p: 0.9, max_tokens: 200, threshold: 0.5, }, } // Função reducer para gerenciar as ações do chat e das configurações do modelo function reducer(state, action) { switch (action.type) { case 'SEND_MESSAGE': return { ...state, chatHistory: [...state.chatHistory, { user: 'Você', message: state.message }], message: '', } case 'UPDATE_MESSAGE': return { ...state, message: action.payload } case 'UPDATE_CONFIG': return { ...state, modelConfig: { ...state.modelConfig, [action.key]: action.value }, } case 'CLEAR_CHAT': return { ...state, chatHistory: [] } default: throw new Error('Ação não reconhecida') } } function AIChatComponent() { const [state, dispatch] = useReducer(reducer, initialState) return ( <div> <h2>Chat com IA</h2> <div> <h3>Histórico</h3> <ul> {state.chatHistory.map((chat, index) => ( <li key={index}> <strong>{chat.user}:</strong> {chat.message} </li> ))} </ul> </div> <div> <h3>Mensagem</h3> <textarea value={state.message} onChange={(e) => dispatch({ type: 'UPDATE_MESSAGE', payload: e.target.value })} placeholder="Digite sua mensagem..." /> <button onClick={() => dispatch({ type: 'SEND_MESSAGE' })}>Enviar</button> <button onClick={() => dispatch({ type: 'CLEAR_CHAT' })}>Limpar Chat</button> </div> <div> <h3>Configurações do Modelo</h3> <label> Temperature: <input type="number" value={state.modelConfig.temperature} step="0.1" min="0" max="1" onChange={(e) => dispatch({ type: 'UPDATE_CONFIG', key: 'temperature', value: parseFloat(e.target.value) })} /> </label> <label> Top K: <input type="number" value={state.modelConfig.top_k} min="1" onChange={(e) => dispatch({ type: 'UPDATE_CONFIG', key: 'top_k', value: parseInt(e.target.value) })} /> </label> <label> Top P: <input type="number" value={state.modelConfig.top_p} step="0.05" min="0" max="1" onChange={(e) => dispatch({ type: 'UPDATE_CONFIG', key: 'top_p', value: parseFloat(e.target.value) })} /> </label> <label> Max Tokens: <input type="number" value={state.modelConfig.max_tokens} min="1" onChange={(e) => dispatch({ type: 'UPDATE_CONFIG', key: 'max_tokens', value: parseInt(e.target.value) })} /> </label> <label> Threshold: <input type="number" value={state.modelConfig.threshold} step="0.05" min="0" max="1" onChange={(e) => dispatch({ type: 'UPDATE_CONFIG', key: 'threshold', value: parseFloat(e.target.value) })} /> </label> </div> </div> ) } // ESSA LINHA É UTILIZADA APENAS PARA O LIVE EDITOR; NÃO FAZ PARTE DO EXEMPLO ACIMA; render(AIChatComponent);
Como funciona?
O useReducer
aceita dois parâmetros principais:
- Reducer function: Função pura que recebe o estado atual e a ação, e retorna o novo estado.
- Estado inicial: Valor inicial do estado, que pode ser qualquer tipo de dado — objeto, array, primitivo, etc.
A função reducer geralmente usa um switch
para decidir qual transformação aplicar no estado com base no tipo da ação recebida.
Depois, o useReducer
retorna um array com duas posições:
- state: O estado atual.
- dispatch: Função que dispara uma ação para atualizar o estado.
Formação
A estrutura básica é:
const [state, dispatch] = useReducer(reducer, initialState)
Por que usar useReducer
?
Se você percebe que está acumulando muitos useState
, ou que precisa de lógica complexa para determinar como o estado deve mudar, o useReducer
é uma escolha natural. Ele te dá mais controle, mantém a lógica de atualização centralizada e facilita a manutenção.
Dica
O useReducer
é especialmente útil quando combinado com Context API
para criar uma solução de gerenciamento de estado global, eliminando a necessidade de bibliotecas externas, dependendo da complexidade do projeto.