react-redux

Redux – Controlando o estado global da sua aplicação.

Quando falamos em ecossistema react, não podemos esquecer do redux, que é um outro framework muito utilizado em conjunto com ele.

O que é o redux?

Para definirmos o que é o redux, temos que antes ter em mente o que é o react, veja em: React – Primeiros Passos, mas para simplificar, react é uma biblioteca que controla os componentes da sua aplicação.

Como o react controla os componentes da sua aplicação o redux controla o estado global da sua aplicação.

Então, redux é um framework de gerenciamento de estado(controle de um estado único na sua aplicação).

O react não faz isso?

A resposta é não. O react tem uma propriedade chamada state, mas este state é apenas do seu componente, você consegue passar este valor para seus filhos através das propriedades, mas receber de volta é uma coisa complicada e passar para o pai deste componente é mais complicado ainda.

Vamos pensar assim, uma aplicação é um conjunto de componentes, uma árvore. E nesta árvore temos várias ramificações.

Cada ramificação é um componente que chama outro componente, que chama outro componente, que chama outro componente, etc..

Imagina você alterando um estado em um componente que foi filho, do filho, do filho do filho do componente A, o componente A4, digamos agora que precisa pegar estas informações no componente C12, imagina o trabalho para pegar isso?

Uma imagem vale mais que mil palavras.

O que eu falei anteriormente pode ser visto e entendido melhor nesta imagem.

Wthout-redux-with-redux

Na primeira árvore temos um exemplo de componentes sem o redux. Perceba que eles conversam apenas com os mais próximos, não conseguem conversar com os que estão mais distantes e isso dificulta e muito o desenvolvimento da nossa aplicação.

Já com redux temos a store, que é a única fonte de verdade da sua aplicação, um estado único para a aplicação, não mais um estado para cada componente.

Tríade do redux.

Um conjunto de princípios compõem o que é o conceito do redux e são eles:

Store:

  • É a única fonte de verdade da sua aplicação.
  • Um estado único para a aplicação, não mais um estado para cada componente.

Action:

  • Um componente dispara uma ação(dispatch) e esta ação gera uma mudança no estado.
  • Todos os componentes que estão registrados neste estado serão renderizados. 
  • Não altera o estado, evolui o estado.
  • O estado é dividido em pequenas partes, as ações alterarão cada pequena parte deste estado, os componentes que estiverem registrados nesta parte sofrerão esta modificação. 
  • Dependendo de onde você estiver na sua aplicação cada parte do estado terá valores diferentes, porém o estado ainda será um objeto único.

Reducer: 

  • São  funções puras que evoluem o estado.
  • Transmitem as alterações emitidas pelas actions e aplicam na store.

Exemplo:

Para entendermos o redux vamos fazer um contador, bem simples, algo fácil de entender.

Como disse anteriormente o redux não é exclusivo do react e para utilizar ele precisamos adicionar um pacote de ligação, o react-redux.

Então utilizaremos os seguintes pacotes npm:

  • react
  • redux
  • react-redux

Passos para a criação:

Você precisará ter o create-react-app instalado, caso não tenha leia:

React – Primeiros Passos

React – Criando o primeiro componente

create-react-app contador-redux

Após o projeto criado navegue até a pasta.

cd contador-redux

Dentro dela inicie o projeto.

npm start

Dentro da pasta src, vamos deletar tudo e criar um index.js do zero. Também vamos criar 3 pastas para separarmos os arquivos indicando o que cada um fará.

Vamos criar então as pastas actions, components e reducers, lembrando, dentro da pasta src.

count-redux

Criaremos dentro da pasta action o arquivo counterAction.js, dentro da pasta reducers o arquivo counterReducer.js e dentro da pasta components o arquivo counter.js

Geralmente criaríamos tudo como counter, mas para ficar mais fácil o entendimento alterei os nomes para adicionar o que cada arquivo é encarregado de fazer.

counter-redux2

Entendendo para fazer.

Vamos fazer um contador, então temos que entender quais as ações que ele tomará.

Temos 3 ações possíveis, incrementar, decrementar e aumentar o “step” do contador, de quanto em quanto ele irá aumentar.

Ótimo, já definimos o que nossas ações farão, então bora programar.

Dentro do arquivo counterActions.js vamos digitar o seguinte código:

action

Não poderia ser mais simples, não é mesmo?

O que estamos falando acima é que, quando chamar a função increment() retornaremos um tipo ‘INCREMENT’.

Quando chamarmos a função decrement() retornaremos um tipo ‘DECREMENT’

E quando chamarmos a função stepChanged(), recebendo como parâmetro e retornaremos um tipo ‘STEP_CHANGED’ e também um payload com o valor recebido deste e.

Ficou difícil de entender?

Imagine assim o action recebe uma chamada, de incrementar o valor e ele passa para o reducer o que precisa fazer, através do tipo ‘INCREMENT’.

No arquivo counterReducer.js vamos digitar o seguinte código.

reducer

Pode parecer estranho no começo, mas depois o entendimento fica mais fácil.

O que fizemos foi criar um estado inicial para o contador, com seu valor (number) começando com 0 (zero) e o step começando com 1 (um).

Logo após iniciar o estado retornamos uma função que recebe um estado e uma ação(state = INITIAL_STATE, action) . 

Dentro desta função testamos qual o tipo da ação foi enviado e retornamos o estado atualizado para a store.

Ficou claro ou ainda ficou confuso?

Vamos pensar assim, o action disparou para o reducer uma ação do tipo ‘INCREMENT’.

O reducer ouviu esta ação e pegou o estado, viu quanto ele tinha que atualizar, (step) (um), e quanto o valia o contador, (number) 0 (zero).

Feito isso ele vai criar um novo estado a partir do estado atual e retornar o valor atualizado para a store, step 1 (um), number 1 (um).

O fluxo do redux seria assim, o componente dispara uma ação, esta ação passa para o reducer qual parte precisa ser alterada da store, o reducer altera esta parte e devolve um novo estado para store e ela por sua vez atualiza o componente.

ReduxFlow

Criando e conectando com o redux

Até agora não criamos nenhum componente react, vamos criar o que vai controlar e disparar as ações.

Dentro da pasta components vamos criar o componente counter.js

counterjs

Agora as coisas ficarão um pouco mais complicadas, mas bem explicadas conseguiremos entender facilmente.

Como disse não podemos utilizar somente o redux com o react sem um outro pacote de ligação. Por isso chamaremos o react-redux

Do redux importamos o bindActionCreators(), que ligará as ações criadas com o dispatchE é só isso mesmo.

Mas como assim?

Calma jovem Padawan, a força está com você, não retire os cabelos.

Eu não disse que o estado será mudado pelas actions? Então, o que estamos fazendo é apenas mapeando as ações e criando o gatilho para elas, você entenderá depois.

E do react-redux estamos importando o connect(), que juntará tudo, o redux com o react.

Como nosso componente não terá que controlar estado, podemos criar um componente funcional, veremos mais sobre isso em um próximo post.

const Count = props => ()

O props será um atributo mapeado pelo redux agora. Nele estarão nossas ações e o nosso estado.

<h1>Contador: {props.counter.number}</h1>

Acima um exemplo de estado: o counter é um atributo do nosso estado global

<button onClick={props.increment}> Incrementar </button>

<button onClick={props.decrement}> Decrementar </button>

Agora um exemplo de action: increment() e decrement(), são actions mapeadas da nossa aplicação.

Mas tudo isso é possível graças a duas funções, mapStateToPros() e mapDispatchToProps().

Na verdade estas ações poderiam ter qualquer nome, mas os criadores do react-redux, indicam colocar estes nomes para que seja mais fácil entender o que as funções fazem e para uma melhor semântica.

mapStateToProps.

A função mapStateToProps() recebe como parâmetro o state global e para cada atributo do state que queremos mapear criaremos um atributo no props, por exemplo:

const mapStateToProps = state => ({counter: state.counter});

Quero que meu props tenha o atributo counter e que pegue este valor de state.counter

Este é um padrão de projeto conhecido como decorator. Ele recebe um componente e retorna o mesmo componente, só que agora decorado, adicionado de novas funcionalidades.

mapDispatchToProps.

A função mapDispatchToProps() recebe como parâmetro o dispatch e retorna o bindActionCreator() que recebe dois parâmetros. O primeiro será um objeto com todas as actions que queremos utilizar e o segundo será o próprio dispatch, que será responsável por disparar todas as ações que foram mapeadas.

const mapDispatchToProps = dispatch => bindActionCreators({ increment, decrement, stepChanged} , dispatch);

Mas tudo isso não faz sentido algum se não ligarmos as funções.

E para isso utilizamos o connect().

export default connect(mapStateToProps, mapDispatchToProps)(Counter)

Estamos conectando ao nosso componente Counter, as propriedades do estado mapeadas e as actions também mapeadas.

Criando a Store

Feito tudo isso temos que criar a store e atribuir o state nela, para isso vamos utilizar o index.js.

 

store

No index.js importamos tudo que iremos utilizar, seja do react, redux, react-redux ou componentes e reducers que criamos.

const reducers = combineReducers({
    counter: counterReducer
})

No código acima estamos criando uma variável reducers, que no nosso caso terá apenas um reducer, o combineReducers(), serve para unir todos os reducers que iremos utilizar na aplicação.

Estamos dizendo que dentro da nossa variável reducers teremos um atributo chamado counter e este atributo receberá o valor de counterReducer, ou seja, todo atributo que for alterado dentro do counterReducer o estado no atributo counter será evoluído.

O createStore() literalmente cria a store, passamos como parâmetro a variável reducers, que já foi tratada anteriormente.

O Provider, que pega o estado e passa para os componentes internos da aplicação.

A aplicação inteira é envolvida pelo provider e tudo que está envolto por ele passa a ser seu filho.

Como o próprio criado do redux Dan Abramov, GitHub, Twitter, Medium diz, você nem sempre precisará do redux para programar em react ou react-native, o nosso exemplo é bem básico e apenas para estudo, apenas para conhecer o funcionamento do redux com react.

Em aplicações simples assim utilizar o redux pode complicar mais ainda a sua vida.

O fato é que, quando precisamos controlar o estado global da nossa aplicação que tenha muitos componente, faça requisições para apis e tenha inúmeras funcionalidades, o redux é uma mão na roda.

Porém pode se tornar um monstro de 7 cabeças se não for bem implementado.

Referências:

https://reactjs.org

https://redux.js.org/

https://github.com/reduxjs/react-redux

https://redux.js.org/basics/usagewithreact

View at Medium.com

View at Medium.com

React – Primeiros Passos

A JavaScript library for building user interfaces – ReactJS

ReactJS ou simplesmente React é uma biblioteca do Facebook (foi desenvolvido pelo Instagram antes do Facebook compra-los ) para criar interfaces de usuário.

Todo programador front-end já ouviu falar no famoso padrão MVC (Model, View, Controller), muito comum nos frameworks como Angular.js(Versão 1.x), Angular (Versões 2 e superiores), Ember.js, Backbone.js e ExtJS.

Então React é mais um framework MVC?

A resposta é não, React não é um framework MVC. Ele é apenas responsável para trabalhar a parte V, ou seja a View.

Sendo assim não conseguimos desenvolver uma aplicação inteira sozinha apenas com React, precisamos de outras bibliotecas e frameworks para fazer isso, diferentemente dos frameworks MVC comuns no mercado.

Então React é um lixo?

Não, embora não tenhamos um framework completo temos todo um ecossistema que é muito bem organizado e mantido pela comunidade do React.

Ecossistema React.

O react é frequentemente utilizado com outro framework chamado Redux(redux.js.org), este ao contrário do react é responsável pelo gerenciamento do estado da nossa aplicação.

Também utilizamos para fazer a cola entre o React e o Redux o react-redux(github.com/reactjs/react-redux).

Para criarmos rotas entre os componentes utilizamos o react-router(github.com/ReactTraining/react-router).

E para conectar com o banco de dados fazendo as requisições http utilizamos o Axios(github.com/axios/axios).

E também podemos desenvolver aplicações mobile tanto para Android quanto para IOS utilizando o React Native(facebook.github.io/react-native).

O React Native é um caso a parte, é mais complexo que o React para web e diferente de outras bibliotecas e frameworks que também criam aplicativos para dispositivos moveis o React Native não cria uma webview.

With React Native, you don’t build a “mobile web app”, an “HTML5 app”, or a “hybrid app”. You build a real mobile app that’s indistinguishable from an app built using Objective-C or Java. React Native uses the same fundamental UI building blocks as regular iOS and Android apps. You just put those building blocks together using JavaScript and React.

Como utilizar o React?

Para começar a utilizar o React você precisa ter o NodeJS instalado.

Caso tenha alguma dúvida pode conferir em Primeiros Passos com NodeJS.

Após o Node instalado temos que instalar o create app do react de forma global.

npm install -g create-react-app

Obs: Se você estiver utilizando mac ou linux provavelmente terá que adicionar um sudo na frente do código para instalação e colocar sua senha de administrador.

Terminada a instalação temos que criar um novo projeto basta digitar:

create-react-app hello-world
Após rodarmos o comando será criada uma estrutura de pastas igual a esta:
estrutura-react
Pronto já temos o esqueleto da nossa aplicação, se entrarmos dentro da pasta hello-world e digitarmos:
npm start
Nosso primeiro exemplo estará funcionando sempre precisemos alterar mais nada.
localhost-react

Como todos sabem da maldição do Hello World, vamos criar um componente que escreva Hello World na tela.

Reza a lenda que o programador que não fizer no seu primeiro código com as instruções que escreva na tela o simples Hello Word ou Olá Mundo, não conseguirá e entender ou aprender nada sopre programação, e nem mesmo conseguira se tornar um bom profissional, será um péssimo programador.

Podemos deletar todos os arquivos que estão dentro da pasta src, menos o App.js e o index.js.

Observe que ao deletar todos os arquivos no terminal apontará um erro, é necessário também deletar a referências destes arquivos nos arquivos que ficaram.

No index.js delete a referência do index.css e do registerServiceWorker.

No App.js delete a referencia do logo e do app.css e todo o corpo dentro da primeira div.

Feito isso a aplicação voltará a funcionar novamente, só que agora teremos uma página em branco.

Então podemos quebrar a maldição do Hello World e escrever um H1 dentro da tag div.

import React, { Component } from 'react';

class App extends Component {
    render() {
        return (
            <div className="App">
                <h1>Hello World!</h1>
            </div>
        );
    }
}

export default App;

Se nossa aplicação estiver rodando basta salva-la que o Hello World! aparecerá na tela, se ela estiver parada, basta digitar novamente no terminal ou prompt de comando no windows npm start.

Entendendo o código.

Na primeira linha estamos importando o React e o Component do módulo react que está dentro da pasta onde_modules.

Então criamos a classe App que irá estender seus atributos e funções do Component.

Uma destas funções e a render(), que será responsável por renderizar a View na tela.

Ele retorna um jsx, que é muito parecido com códigos html puros, mas diferem por algumas coisas.

Dentro do nosso retorno da da função render(), temos que nos atentar a duas coisas que no começo apanhei e muitos desenvolvedores apanham até se acostumar:

  • className ao invés de class.
  • Uma tag para englobar todas as outras tags

A palavra class é reservada do javascript, então a class do html se transforma em className.

Dentro do retorno temos que utilizar apenas uma tag para envolver as outras tags, se utilizarmos mais duas divs por exemplo sem que uma outra div as tenha englobado ocorrerá um erro. Veja o que ocorre quando adicionamos mais uma div abaixo da que já está no código.

errojsx