React + Redux

O estado de componente no React funciona bem até que múltiplos componentes precisem dos mesmos dados e o prop drilling vira algo insuportável. O Redux fornece um container de estado único e previsível que qualquer componente pode ler e para o qual pode disparar ações.

TL;DR: Uma referência React + Redux: setup do store, actions, reducers, selectors e middleware Thunk para operações assíncronas.
Stack: React, Redux, Redux Toolkit, React-Redux
Nível: Intermediário
Tempo de leitura: ~18 min

O problema que o Redux resolve

Em um app típico, você tem muitos componentes cada um com seu próprio estado. Quando os componentes começam a depender dos dados uns dos outros, você acaba passando props por camadas de componentes que nem as usam , isso é prop drilling. O Redux move o estado compartilhado para fora dos componentes e para dentro de um store central, para que qualquer componente possa ler ou atualizar sem uma cadeia de relay de props.

Setup

npx create-react-app meu-app
yarn add redux react-redux immer
yarn add redux-devtools-extension

Reducer (store/modules/shop/reducer.js)

import produce from 'immer';

const INITIAL_STATE = { customer: {}, items: [] };

function shop(state = INITIAL_STATE, action) {
    switch (action.type) {
        case 'SET_CUSTOMER':
            return produce(state, (draft) => {
                draft.customer = action.customer;
            });
        case 'ADD_ITEM':
            return produce(state, (draft) => {
                draft.items.push(action.item);
            });
        default:
            return state;
    }
}

export default shop;

Root reducer e store (store/index.js)

import { combineReducers } from 'redux';
import shop from './modules/shop/reducer';
export default combineReducers({ shop });

// store/index.js
import { createStore } from 'redux';
import rootReducer from './modules/rootReducer';
const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__?.());
export default store;

Conectar ao app (index.js)

import { Provider } from 'react-redux';
import store from './store';

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
);

Disparando actions

import { useDispatch } from 'react-redux';

const dispatch = useDispatch();
dispatch({ type: 'SET_CUSTOMER', customer: { name: 'Allan', age: 30 } });

Lendo do store

import { useSelector } from 'react-redux';

const customer = useSelector((state) => state.shop.customer);
const items = useSelector((state) => state.shop.items);

O que você construiu

Um setup Redux com estado centralizado, actions, reducers usando Immer para imutabilidade, e hooks para leitura e dispatch.

Próximos passos

  • Use o Redux Toolkit (createSlice, createAsyncThunk) em vez do Redux puro. Elimina a maior parte do boilerplate e é a abordagem oficial recomendada.
  • Use selectors com memoização via reselect para evitar re-renders desnecessários ao ler do store.
  • Redux é excessivo para muitos apps. Para estado do servidor (dados de API), React Query ou SWR é mais simples, e para estado de UI local, useState e useContext geralmente bastam.

Dúvidas ou feedback? Me encontre no LinkedIn ou GitHub.

Deixe um comentário