O gerenciamento de estado em aplicações React complexas apresenta desafios únicos. Redux oferece uma arquitetura centralizada e previsível, enquanto a Context API fornece uma solução nativa mais simples. A combinação dessas tecnologias pode maximizar os benefícios de ambas as abordagens.

Redux facilita o controle de mudanças através de actions e reducers, mas pode gerar código verboso. A Context API elimina prop drilling sem configuração adicional, porém não oferece a mesma estrutura para aplicações grandes. Integrar ambas permite segmentar responsabilidades conforme a complexidade de cada funcionalidade.

Configuração Inicial do Projeto

Inicie criando um novo projeto React com as ferramentas necessárias. Certifique-se de ter Node.js versão 14 ou superior instalado no sistema.

npx create-react-app redux-context-integration
cd redux-context-integration
npm install redux react-redux @reduxjs/toolkit

Utilize o Redux Toolkit para simplificar a configuração e reduzir código boilerplate. Esta ferramenta oficial oferece utilities que tornam o Redux mais produtivo e eficiente.

Configuração do Redux Store

Crie a estrutura do Redux com Redux Toolkit, que simplifica significantly a configuração tradicional:

// src/store/counterSlice.js
import { createSlice } from \'@reduxjs/toolkit\'

const counterSlice = createSlice({
  name: \'counter\',
  initialState: {
    value: 0,
    history: []
  },
  reducers: {
    increment: (state) => {
      state.value += 1
      state.history.push(
Incrementado para ${state.value}
) }, decrement: (state) => { state.value -= 1 state.history.push(
Decrementado para ${state.value}
) }, incrementByAmount: (state, action) => { state.value += action.payload state.history.push(
Incrementado por ${action.payload}
) } } }) export const { increment, decrement, incrementByAmount } = counterSlice.actions export default counterSlice.reducer

Configure o store principal combinando todos os reducers da aplicação:

// src/store/index.js
import { configureStore } from \'@reduxjs/toolkit\'
import counterReducer from \'./counterSlice\'

const store = configureStore({
  reducer: {
    counter: counterReducer
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [\'persist/PERSIST\']
      }
    })
})

export default store

Implementação da Context API

A Context API gerenciará dados de sessão, preferências do usuário e estados temporários que não precisam persistir no Redux:

// src/contexts/AppContext.js
import React, { createContext, useContext, useReducer } from \'react\'

const AppContext = createContext()

const initialState = {
  theme: \'light\',
  language: \'pt-BR\',
  notifications: [],
  tempData: {}
}

function appReducer(state, action) {
  switch (action.type) {
    case \'SET_THEME\':
      return { ...state, theme: action.payload }
    case \'ADD_NOTIFICATION\':
      return {
        ...state,
        notifications: [...state.notifications, action.payload]
      }
    case \'REMOVE_NOTIFICATION\':
      return {
        ...state,
        notifications: state.notifications.filter(
          (notification) => notification.id !== action.payload
        )
      }
    case \'SET_TEMP_DATA\':
      return {
        ...state,
        tempData: { ...state.tempData, ...action.payload }
      }
    default:
      return state
  }
}

export function AppProvider({ children }) {
  const [state, dispatch] = useReducer(appReducer, initialState)
  
  return (
    
      {children}
    
  )
}

export const useApp = () => {
  const context = useContext(AppContext)
  if (!context) {
    throw new Error(\'useApp deve ser usado dentro de AppProvider\')
  }
  return context
}

Integração Completa no App Principal

Configure o App.js para utilizar ambos os providers simultaneamente:

// src/App.js
import React from \'react\'
import { Provider } from \'react-redux\'
import store from \'./store\'
import { AppProvider } from \'./contexts/AppContext\'
import Counter from \'./components/Counter\'
import ThemeToggle from \'./components/ThemeToggle\'

function App() {
  return (
    
      
        
) } export default App

Componente Prático: Counter Integrado

Desenvolva um componente que demonstra a integração prática entre Redux e Context API:

// src/components/Counter.js
import React from \'react\'
import { useSelector, useDispatch } from \'react-redux\'
import { increment, decrement, incrementByAmount } from \'../store/counterSlice\'
import { useApp } from \'../contexts/AppContext\'

function Counter() {
  const count = useSelector((state) => state.counter.value)
  const history = useSelector((state) => state.counter.history)
  const dispatch = useDispatch()
  const { state: appState, dispatch: appDispatch } = useApp()
  
  const handleIncrement = () => {
    dispatch(increment())
    appDispatch({
      type: \'ADD_NOTIFICATION\',
      payload: {
        id: Date.now(),
        message: \'Contador incrementado!\',
        type: \'success\'
      }
    })
  }
  
  const handleCustomIncrement = () => {
    const amount = parseInt(appState.tempData.customAmount) || 1
    dispatch(incrementByAmount(amount))
  }
  
  return (
    
counter-container theme-${appState.theme}
}>

Contador: {count}

appDispatch({ type: \'SET_TEMP_DATA\', payload: { customAmount: e.target.value } })} />

Histórico:

    {history.slice(-5).map((entry, index) => (
  • {entry}
  • ))}
{appState.notifications.map((notification) => (
notification ${notification.type}}> {notification.message}
))}