DEV Community

Aldcejam
Aldcejam

Posted on

POR QUE e COMO USAR o Redux??

Redux com Toolkit no ReactJS/NextJS

Quer aprender apenas analisando um código?

Vá ao repositório: https://github.com/aldcejam/Tutorial_Redux-toolkit

O README do projeto diz quais os arquivos necessários para que o Redux funcione
Os commits do projeto seguem a sequência deste tutorial pós instalação

Os porquês:

  1. Organização do estado: O Redux ajuda a manter todas as informações importantes do seu aplicativo organizadas em um só lugar, facilitando o controle e a compreensão.
  2. Fluxo de dados controlado: Com o Redux, você tem um fluxo de dados bem definido, o que torna mais fácil entender como as coisas funcionam e evita problemas inesperados.
  3. Escalabilidade: Se o seu aplicativo está ficando grande e complexo, o Redux oferece uma maneira de gerenciar tudo de forma mais estruturada, facilitando a manutenção e o desenvolvimento contínuo.
  4. Compatibilidade com outras bibliotecas: O Redux é amplamente utilizado em projetos JavaScript e funciona bem com várias bibliotecas e frameworks populares, como React, Angular e Vue.js.
  5. Ferramentas para desenvolvedores: O Redux oferece ferramentas que ajudam no desenvolvimento, depuração e monitoramento do estado do aplicativo, tornando o processo mais fácil e eficiente.

ADENDO: Não é preciso utilizar o Redux para gerenciar todos os estados globais da sua aplicação. Se você tiver um caso simples, como configurar o tema do seu aplicativo, recomendo usar o Context do React.

Como usar:

Etapa 1: Instalação

yarn:

yarn add react-redux @reduxjs/toolkit
Enter fullscreen mode Exit fullscreen mode

npm

npm install react-redux @reduxjs/toolkit
Enter fullscreen mode Exit fullscreen mode

Etapa 2: Configurações:

Crie uma pasta para conter os arquivos hook.ts e o store.ts do Redux

|-- src
    |-- redux.config
        |-- hook.ts
        |-- store.ts
Enter fullscreen mode Exit fullscreen mode

Arquivo hook.ts

Este arquivo será responsável pela tipagem dos estados do Redux.

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'

export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
Enter fullscreen mode Exit fullscreen mode

Arquivo store.ts

Este arquivo será responsável por centralizar os estados Redux.
Neste arquivo você só precisa entender que cada item em reducer é um Estado Redux, ou seja, cada novo estado redux que criar, o adicione no objeto reducer.

import { configureStore,ThunkAction,Action } from '@reduxjs/toolkit' 
/* import EstadoRedux from "caminho" */

export const Store = configureStore({
  reducer: {
    /* NomeDoEstado: EstadoRedux, */
  },
});

export type AppDispatch = typeof Store.dispatch;
export type RootState = ReturnType<typeof Store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>;
Enter fullscreen mode Exit fullscreen mode

Agora vamos configurar o provider para que todos os nossos componentes e páginas possam acessar os estados do Redux.

caso não esteja utilizando o diretório app com layouts do NextJS
versão 13+, apenas coloque o provider no arquivo _app.ts.

o layout pai de todos ficará assim:

"use client"
import { Provider } from 'react-redux'
import { Store } from '@/redux.config/store'
import './globals.css' 


export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="pt-br">
      <Provider store={Store}>
        <body>{children}</body>
      </Provider>
    </html>
  )
}

Enter fullscreen mode Exit fullscreen mode

Etapa 3: Criar estado redux

O nome do estado será "ShoppingCartData" e terá dois estados, um de string ID e outro de objeto com itens de compra e sua quantidade.

{
   id: string
   itens: {
      carne: string
      arroz: string
   }
}
Enter fullscreen mode Exit fullscreen mode

Siga estas etapas para se manter organizado:

  1. Vamos criar a pasta @core em src para centralizar os estados
  2. Vamos criar uma pasta com o nome do nosso estado
  3. Agora vamos criar um arquivo ShoppingCartData.ts e ShoppingCartData.d.ts para a tipagem
|-- src
    |-- @core
        |-- ShoppingCartData
            |-- ShoppingCartData.ts
            |-- IShoppingCartData.d.ts
Enter fullscreen mode Exit fullscreen mode

no arquivo ShoppingCartData.ts podemos fazer o seguinte código inicial padrão:

import { RootState } from "@/redux.config/store";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

const initialState = {

}

export const ShoppingCartDataSlice = createSlice({
    name: "ShoppingCartData",
    initialState,
    reducers: {
    }
})

export const { } = ShoppingCartDataSlice.actions

export const ShoppingCartDataStates = (state: RootState) => state.ShoppingCartData

export default ShoppingCartDataSlice.reducer
Enter fullscreen mode Exit fullscreen mode

O objeto InitialStates é o responsável por ter todos os estados deste Redux
O objeto reducers será o responsável por ter todos os setState dos estados em InitialStates

Agora para fazer toda tipagem para o arquivo ShoppingCartData.ts vamos usar o arquivo IShoppingCartData.d.ts. Dado os estados previamente previstos temos a seguinte tipagem:

type IDProps = string
type ShoppingCartItemsProps = {
    [itemName: string]: string;
}

interface IShoppingCartDataProps {
    ID: IDProps;
    shoppingCartItems: ShoppingCartItemsProps;
}

export { IShoppingCartDataProps, IDProps, ShoppingCartItemsProps}
Enter fullscreen mode Exit fullscreen mode

A tipagem dos itens de IShoppingCartDataProps não são atoa, brevemente você entenderá o motivo.

Agora, com a tipagem estabelecida podemos adicionar os estados de initialStates e os reducers no nosso arquivo ShoppingCartData.ts

import { RootState } from "@/redux.config/store";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { IDProps, IShoppingCartDataProps, ShoppingCartItemsProps } from "./IShoppingCartData"

const initialState: IShoppingCartDataProps = {
    ID: "" as IDProps,
    shoppingCartItems: {} as ShoppingCartItemsProps
}

export const ShoppingCartDataSlice = createSlice({
    name: "ShoppingCartData",
    initialState,
    reducers: {
        setID: (state, action: PayloadAction<IDProps>) => {
            state.ID = action.payload
        },
        setShoppingCartItems: (state, action: PayloadAction<ShoppingCartItemsProps>) => {
            state.shoppingCartItems = action.payload
        }
    }
})

export const {
    setID,
    setShoppingCartItems

} = ShoppingCartDataSlice.actions

export const ShoppingCartDataStates = (state: RootState) => state.ShoppingCartData

export default ShoppingCartDataSlice.reducer
Enter fullscreen mode Exit fullscreen mode

Perceba as seguintes etapas
etapa 1: importação das tipagens do arquivo ShoppingCartData.d.ts.
etapa 2: atribuição da tipagem "IShoppingCartDataProps" em InitialStates.
etapa 3: implementação de valores iniciais para os estados de InitialStates (agora obrigatórios devido a tipagem).
etapa 4: criação dos reducers para cada item de InitialStates. Perceba que tipamos o valor a ser recebido na função set quando colocamos "action: PayloadAction< IDProps>", logo, o state a ser passado para o setID terá que ser um valor do tipo IDProps.
etapa 5: para finalizar exportamos os Set do reducers

para finalizar a etapa 3 podemos importar nosso ShoppingCartData para o store.ts. O arquivo ficará assim:
store.ts:

import ShoppingCartData from '@/@core/ShoppingCartData/ShoppingCartData';
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit'


export const Store = configureStore({
    reducer: {
        ShoppingCartData,
    },
});

export type AppDispatch = typeof Store.dispatch;
export type RootState = ReturnType<typeof Store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
    ReturnType,
    RootState,
    unknown,
    Action<string>
>;
Enter fullscreen mode Exit fullscreen mode

O ShoppingCartData importado é o export default do arquivo ShoppingCartData.ts

Etapa 4: Como MODIFICAR e CONSUMIR os estados

Consumir:

"use client"
import { ShoppingCartDataStates } from '@/@core/ShoppingCartData/ShoppingCartData'
import { useAppSelector } from '@/redux.config/hook'

const id = useAppSelector(ShoppingCartDataStates).ID
const shoppingCartItems = useAppSelector(ShoppingCartDataStates).shoppingCartItems
Enter fullscreen mode Exit fullscreen mode

Modificar:

"use client"
import { setID, setShoppingCartItems } from '@/@core/ShoppingCartData/ShoppingCartData'
import { useAppDispatch } from '@/redux.config/hook'

const dispatch = useAppDispatch();
const modificarID = ()=> dispatch(setID("999"))
const modificarShoppingCartItems = () => dispatch(setShoppingCartItems({
    carne: "2kg",
    arroz: "1kg"
}))
Enter fullscreen mode Exit fullscreen mode

Top comments (0)