Você está na página 1de 10

React Brasil Sign in Get started

Follow 5.1K Followers · Arquivados Off-topics React Conf Brasil About

Iniciando com Redux em 9


passos
Este tutorial será o mais curto e objetivo sobre Redux que você vai
encontrar!

Rafael Maruta Feb 14, 2018 · 9 min read

Boa tarde pessoal! Tudo bem?

Com este artigo pretendo engajar aqueles que estão iniciando com
Redux, focando apenas nas partes básicas, usando o mínimo de
implementação para que funcione. Recomendo um conhecimento básico
de React, JSX, ES6+, e também alguns termos de programação
funcional.

Este artigo não contempla:

As razões para se usar Redux. Caso você queira saber mais, deixo-lhes
aqui um artigo: https://medium.com/trainingcenter/tira-redux-
coloca-redux-eb3c4f1d7db8

Redux Middlewares, provavelmente em um artigo futuro.

Testes, talvez em um artigo futuro também. Mas se estiver curioso,


aqui tem um artigo da própria documentação:
http://redux.js.org/docs/recipes/WritingTests.html

No final do tutorial deixei o link do repositório com o exemplo funcional.


Dividi o tutorial em 9 passos.

Primeiramente explicarei brevemente a arquitetura do Redux

Arquitetura do Redux
O Redux é uma implementação criada pelo Dan Abramov da
arquitetura Flux, que foi criada pelo Facebook. Ela soluciona o
problema de compartilhamento de estados entre componentes,
tornando-o unidirecional. A ilustração a seguir descreve tudo:
À esquerda é o problema da dificuldade de transmissão de estados, e à direita é a solução proposta pelo
Redux

Através da ilustração percebemos que o Redux simplesmente simplifica a


evolução de estados de uma aplicação quando há múltiplos estados para
controlar e muitos componentes que precisam atualizar ou se inscrever
nessa evolução, tirando a responsabilidade de cada componente de
guardar o estado e passando para uma centralizada e única Store.

Fluxo de uma evolução de estado


Como uma imagem vale mais do que mil palavras, segue abaixo um
diagrama que mostra como funciona o fluxo de uma evolução de estado
com Redux, com a explicação de cada parte a seguir.

Imagem extraída de https://itnext.io/integrating-semantic-ui-modal-with-redux-4df36abb755c

Para realizar tal fluxo, o Redux depende de 4 partes:

Store: é o container que armazena e centraliza o estado geral da


aplicação. Ela é imutável, ou seja, nunca se altera, apenas evolui.

Podemos ter apenas uma Store por aplicação, ou seja, ela é a Única Fonte
de Verdade (Single Source of Truth).

Actions: são fontes de informações que são enviadas da aplicação


para a Store. São disparadas pelas Action Creators, que são simples
funções que, ao serem executadas, ativam os Reducers.

Reducers: recebem e tratam as informações para que sejam ou não


enviadas à Store.
Conexão dos componentes ao Redux: para poderem se inscrever à
evolução de estados da Store ou disparar eventos para evoluí-la.

Pode não ter ficado muito claro agora, mas não precisa se preocupar,
pois com a aplicação será mais fácil de entender. Caso queira
informações mais detalhadas, recomendo a leitura da documentação
oficial:

https://redux.js.org/

1. Instale e rode o Create React App


Create React App é um boilerplate criado pelo Facebook para iniciar
rapidamente um projeto com React. Ele já vem com algumas
dependências e plugins instalados, além de algumas pré-configurações.

Caso você possua npm 5.2+ ou maior, poderá instalar desta forma:

npx create-react-app create-react-redux-app

Se não tiver, é necessário instalar o Create React App globalmente. Rode


em seu terminal o comando:

npm i -g create-react-app

… e ao finalizar:

create-react-app create-react-redux-app

O create-react-redux-app é o nome da pasta que será criada. Agora entre


na pasta:

cd create-react-redux-app

… e rode com Yarn:

yarn start

ou com npm:

npm start

Uma janela no navegador abrirá, na porta http://localhost:3000/


exibindo:
Print do navegador exibindo a tela inicial do Create React App

2. Adapte a View para o tutorial


Acesse o arquivo create-react-redux-app/src/App.js e substitua a
marcação (negritei as mudanças):

import React, { Component } from 'react';


import './App.css';

class App extends Component {


render() {
return (
<div className="App" style={{ paddingTop: '10px' }}>
<input type='text' />
<button>
Click me!
</button>
<h1>teste</h1>
</div>
);
}
}

export default App;

Ficará parecido com isto:

Bonitão não?

A idéia é que, quando clicarmos no botão Click me!, o texto "teste" seja
substituído pelo conteúdo que está no input, via Redux.

3. Instale o Redux e o React Redux


O Redux é a lib de container de estados, enquanto o React Redux realiza
a conexão entre React e o Redux.

No terminal no diretório do exemplo onde está o package.json, rode:

Para Yarn:

yarn add --dev redux react-redux

Para npm:
npm i -D redux react-redux

4. Crie a Store
Crie uma pasta na raíz da pasta /src chamada store. Dentro dela, crie
um arquivo index.js com o conteúdo:

import { createStore } from 'redux';


import { Reducers } from '../reducers';

export const Store = createStore(Reducers);

Aqui criamos a Store e dizemos quais são os seus respectivos Reducers.


Vamos criá-los adiante.

5. Crie o Reducer
Como a Store é a Única Fonte de Verdade, teremos que combinar todos
os reducers da aplicação e enviar à Store. Crie uma pasta na raíz da pasta
/src chamada reducers. Dentro dela, crie um arquivo index.js com o
conteúdo:

import { clickReducer } from './clickReducer';


import { OtherReducer } from './otherReducer';
import { combineReducers } from 'redux';

export const Reducers = combineReducers({


clickState: clickReducer,
otherState: otherReducer
});

Caso sua aplicação possua vários reducers, você pode combiná-los para
enviá-los à Store da seguinte forma, usando o método combineReducers .

A chave do objeto é o nome na qual o estado será acessado pela


aplicação, enquanto o seu valor é o Reducer, função pura que filtra os
dados e que criaremos adiante. Ficará de sua escolha caso prefira usar o
mesmo nome para a chave e valor.

Aqui definimos qual será a chave do Reducer na Store quando quisermos


acessar o seu estado, além de podermos combinar vários Reducers para
serem conectados à Store.

Crie o arquivo clickReducer.js na mesma pasta com o seguinte


conteúdo:

const initialState = {
newValue: ''
};

export const clickReducer = (state = initialState, action) => {


switch (action.type) {
case 'CLICK_UPDATE_VALUE':
return {
...state,
newValue: action.newValue
};
default:
return state;
}
};
Este será o nosso Reducer que será acionado pela Action caso o type dela
seja CLICK_UPDATE_VALUE , caso contrário manterá o estado atual.

IMPORTANTE: esta função deverá ser pura, ou seja, retornar um novo


objeto, pois lembrando, a Store é imutável. Conseguimos preservar o
restante do estado usando o ...state , que recupera o estado anterior e
passa para o novo objeto.

O código abaixo está sujeito a bugs:

export const clickReducer = (state = initialState, action) => {


switch (action.type) {
case 'CLICK_UPDATE_VALUE':
return state.newValue = action.newValue;
default:
return state;
}
}

Agora vamos criar a Action.

6. Crie a Action e sua Action Creator


Crie uma pasta na raíz da pasta /src chamada actions. Dentro dela, crie
um arquivo index.js com o conteúdo:

export const clickButton = value => ({


type: 'CLICK_UPDATE_VALUE',
newValue: value
});

Aqui a função é a Action Creator, e o que ela retorna, que é o objeto, é a


Action. Ao ser disparada, ela comunicará ao Reducer que o type é
CLICK_UPDATE_VALUE , além do valor newValue: value que deverá ser
atualizado na Store. Novamente aqui, caso prefira usar o mesmo nome
para chave e valor, ficará de sua escolha.

Os types, que são as Action Types, recomendo separar num arquivo


próprio para importarmos apenas as constantes, desta forma, num
arquivo:

src/actions/actionTypes.js:

export const CLICK_UPDATE_VALUE = 'CLICK_UPDATE_VALUE';

src/reducers/clickReducer.js atualizado:

import { CLICK_UPDATE_VALUE } from '../actions/actionTypes';

const initialState = {
newValue: ''
};

export const clickReducer = (state = initialState, action) => {


switch (action.type) {
case CLICK_UPDATE_VALUE:
return {
...state,
newValue: action.newValue
};
default:
return state;
}
};

src/actions/index.js atualizado:

import { CLICK_UPDATE_VALUE } from './actionTypes';

export const clickButton = value => ({


type: CLICK_UPDATE_VALUE,
newValue: value
});

Chegou o esperado momento de fazermos a conexão com os


componentes!

7. Crie o Provider para conectar a aplicação à Store


No arquivo src/index.js faça algumas alterações, ele deverá ficar assim
(negritei as mudanças):

import React from 'react';


import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'react-redux';
import { Store } from './store';

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

registerServiceWorker();

Aqui é onde o estado da Store se conectará com toda a aplicação, através


do Provider Pattern, que possibilita que a Store seja acessível a todos os
componentes abaixo dele. Veja mais sobre em:

https://medium.com/@oieduardorabelo/padrões-em-react-provider-
pattern-b520c37ed733

8. Conecte o estado da Store ao componente


Para fazer a conexão com a Store, agora devemos atualizar o nosso
componente src/App.js:

import React, { Component } from 'react';


import { connect } from 'react-redux';
import './App.css';

class App extends Component {


render() {
const { newValue } = this.props;

return (
<div className="App" style={{ paddingTop: '10px' }}>
<input type='text' />
<button>
Click me!
</button>
<h1>{newValue}</h1>
</div>
);
}
}

const mapStateToProps = store => ({


newValue: store.clickState.newValue
});

export default connect(mapStateToProps)(App);

O método mapStateToProps transforma um trecho do estado da Store em


uma prop utilizável pelo componente, com o nome newValue .

Ao acessarmos a chave clickState , que foi definida no arquivo


src/reducers/index.js na linha 5:

clickState: clickReducer

… podemos extrair a sua chave newValue , que foi definida no arquivo


src/reducers/clickReducer.js na linha 12:

newValue: action.newValue

No momento de exportar o componente, precisamos fazer a sua


conexão através do método connect do React Redux, passando o método
mapStateToProps como parâmetro e o componente atual como
parâmetro na função retornada. Este padrão no React se chama High
Order Component.

Ao fazermos esta conexão, podemos usar o newValue como prop no


componente:

...
const { newValue } = this.props;
...

...
<h1>{newValue}</h1>
...

Para sabermos se está funcionando, basta trocarmos o initialState no


arquivo src/reducers/clickReducer.js na linha 4 e conferirmos se
reflete na página:

const initialState = {
newValue: 'Atualizado via Redux!'
};
Nossa tela atualizada, garantindo que a conexão com a Store foi bem sucedida!

9. Disparando um evento para evoluir a Store


Agora vamos criar a funcionalidade de evoluir o estado da Store a partir
do preenchimento do input e o clique no botão Click me!. O código
deverá novamente ser atualizado conforme a seguir:

import React, { Component } from 'react';


import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { clickButton } from './actions';
import './App.css';

class App extends Component {


state = {
inputValue: ''
}

inputChange = event => {


this.setState({
inputValue: event.target.value
})
}

render() {
const {
clickButton,
newValue
} = this.props;

const { inputValue } = this.state;

return (
<div className="App" style={{ paddingTop: '10px' }}>
<input
onChange={this.inputChange}
type='text'
value={inputValue}
/>
<button onClick={() => clickButton(inputValue)}>
Click me!
</button>
<h1>{newValue}</h1>
</div>
);
}
}

const mapStateToProps = store => ({


newValue: store.clickState.newValue
});

const mapDispatchToProps = dispatch =>


bindActionCreators({ clickButton }, dispatch);

export default connect(mapStateToProps, mapDispatchToProps)(App);

Criamos o método mapDispatchToProps para converter a Action Creator


clickButton que criamos no arquivo src/actions/index.js em uma prop
para o componente. O método bindActionCreators facilita este trabalho.
Ao clicar no botão Click me!, o valor do state inputValue que foi
alterado pelo input text é enviado à Store pelo método clickButton , que

foi mapeado no componente como prop.

Por fim, passamos o método mapDispatchToProps como segundo


parâmetro do método connect . Agora é só testar!
Funcionou! =D

É importante lembrar que há diversas formas de se disparar eventos à Store,


eu abordarei algumas delas em um futuro artigo.

Conclusão
Por enquanto isto é tudo pessoal. Segue o link do repositório com o
exemplo:

https://github.com/rafaelmaruta/create-react-redux-app

Caso eu tenha esquecido de algo importante, ou tenha ficado confuso, ou


a melhorar, ou vocês tenham dúvidas, algo a acrescentar, por favor
deixem nos comentários! Lembrando que não contemplei os Redux
Middlewares, que provavelmente ficará para um próximo artigo!

Espero que tenham gostado! E muito obrigado por terem acompanhado!

Recomendação de cursos
https://egghead.io/courses/getting-started-with-redux

https://www.udemy.com/react-redux-pt

https://www.udemy.com/curso-reactjs-ninja

React Redux Create React App JavaScript Immutability

3.4K 29

More from React Brasil Follow

Tudo sobre o mundo React

Read more from React Brasil

About Write Help Legal

Você também pode gostar