UTILIZANDO REDUX NO
DESENVOLVIMENTO DE
APLICAÇÕES EM REACT
ARMANDO AUGUSTUS FREIRE
Análise e desenvolvimento de sistemas,
Desenvolvimento front-end e apaixonado por UX
GABRIEL TOSTA
Análise e desenvolvimento de sistemas
Focado em performance e boas práticas,
desenvolvedor front-end e mobile híbrido
REACT
Declarativa e baseada em components
1
Declarativa
Desenvolvimento das
views. React renderiza
apenas quando os dados
da aplicação forem
alterados
REACT
Components
Componentes
encapsulados possuem
seu próprio estado.
Com a lógica no JS
podemos ter dados
complexos no App sem
impactar diretamente a
DOM
REDUX
Gerenciamento de estado da aplicação
1
CONTROLAR MUTAÇÃO E
SINCRONIA ENTRE COMPONENTES
Manipular apenas o state da aplicação,
evitando manipulação direta da DOM.
Mutações passam a ser previsíveis
quando colocamos restrições em como e
quando elas ocorrem.
TRÊS PRINCÍPIOS DO REDUX
Single source of truth
O estado da aplicação
é armazenado em um
objeto e disponibilizado
através de uma Store
State is read-only
A única forma de
mudar o state da
aplicação é emitindo
um action (objeto)
descrevendo o que
aconteceu
Changes are made
with pure functions
Para especificar
como o state é
alterado por uma
action, usamos
funções JS puras
chamadas reducers
SINGLE SOURCE
OF TRUTH
CHANGES ARE
MADE WITH PURE
FUNCTIONS
Impure fn Pure fn
function impure(a, b) {
return a + b * 2;
}
function pure(a, b) {
return a + b;
}
const pure = (a, b) => {
return a + b;
}
STATE IS READ-ONLY
State is Read-Only
let hasChanged = false;
const nextState = {};
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i];
const reducer = finalReducers[key];
const previousStateForKey = state[key];
const nextStateForKey = reducer(previousStateForKey, action);
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action);
throw new Error(errorMessage);
}
nextState[key] = nextStateForKey;
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
}
return hasChanged ? nextState : state;
Gera um novo estado a partir
dos dados retornados pelo
reducer
Compara a referência em
memória do novo estado com o
estado anterior
Retorna o novo estado caso
seja um novo objeto
Reducer
function reducer(state = initialState, action) {
switch (action.type) {
case 'ADD_COUNTER':
return {
...state,
counter: state.counter + action.value
};
case SUB_COUNTER':
return {
...state,
counter: state.counter - action.value
};
default:
return state;
}
}
...state
=
{
counter: 0,
savedCounters: []
}
DATA FLOW
ACTION REDUCER STORE VIEW
DISPATCH
LIBS & STUFF
REACT
Renderização de
componentes
REACT-DOM
render – manipulação do
DOM
REDUX
Core, util para configurações da store e
separação de contextos dos reducers
REACT-REDUX
Utilizada para conectar componentes React na store
BABEL
Responsável por transpilar
es6 para es5
Reducer
/Action
const mapDispatchToProps = (dispatch) => ({
addCounter() {
dispatch({ type: 'ADD_COUNTER', value: 1 })
}
});
const initialState = { counter: 0 };
function counterReducer(state = initialState, action) {
switch(action.type) {
case 'ADD_COUNTER':
return {
...state,
counter: state.counter + action.value
};
default:
return state;
}
}
Store &
Middleware
import * as Redux from 'redux';
import createLogger from 'redux-logger';
import reducer from './modules/reducer';
const middlewares = [
createLogger()
];
export default function configureStore() {
return Redux.createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__(),
Redux.applyMiddleware(...middlewares)
);
}
Rendering
ReactDOM.render(
<ReactRedux.Provider store={ reduxStore }>
<AppContainer />
</ReactRedux.Provider>,
document.getElementById('root'),
);
Container
component
class AppContainer extends React.Component {
render() {
return (
<App { ...this.props } />
);
}
}
const mapStateToProps = (state) => {
return (
state
);
}
const mapDispatchToProps = (dispatch) => ({
addCounter() {
dispatch({ type: 'ADD_COUNTER', value: 1 })
}
})
const AppContainer =
ReactRedux.connect(
mapStateToProps,
mapDispatchToProps)(AppContainer);
Presentional
component /
View
const App = (props) => {
return (
<div>
<div>{ props.counter }</div>
<button
onClick={() => props.addCounter() }
>
ADD
</button>
</div>
);
}
goo.gl/blaEbL goo.gl/avxvYe
REDUX DEVTOOLS
Time travel, TreeState chart
1
Obrigado!
Perguntas?
Twitter - @armandofreire
armandofreire.it@gmail.com
LinkedIn - @gtosta96
gabrieltosta3@gmail.com

TDC2017 | Florianopolis - Trilha DevOps How we figured out we had a SRE team at JavaScript

  • 1.
    UTILIZANDO REDUX NO DESENVOLVIMENTODE APLICAÇÕES EM REACT
  • 2.
    ARMANDO AUGUSTUS FREIRE Análisee desenvolvimento de sistemas, Desenvolvimento front-end e apaixonado por UX GABRIEL TOSTA Análise e desenvolvimento de sistemas Focado em performance e boas práticas, desenvolvedor front-end e mobile híbrido
  • 3.
  • 4.
    Declarativa Desenvolvimento das views. Reactrenderiza apenas quando os dados da aplicação forem alterados REACT Components Componentes encapsulados possuem seu próprio estado. Com a lógica no JS podemos ter dados complexos no App sem impactar diretamente a DOM
  • 5.
  • 6.
    CONTROLAR MUTAÇÃO E SINCRONIAENTRE COMPONENTES Manipular apenas o state da aplicação, evitando manipulação direta da DOM. Mutações passam a ser previsíveis quando colocamos restrições em como e quando elas ocorrem.
  • 7.
    TRÊS PRINCÍPIOS DOREDUX Single source of truth O estado da aplicação é armazenado em um objeto e disponibilizado através de uma Store State is read-only A única forma de mudar o state da aplicação é emitindo um action (objeto) descrevendo o que aconteceu Changes are made with pure functions Para especificar como o state é alterado por uma action, usamos funções JS puras chamadas reducers
  • 8.
  • 9.
    CHANGES ARE MADE WITHPURE FUNCTIONS
  • 10.
    Impure fn Purefn function impure(a, b) { return a + b * 2; } function pure(a, b) { return a + b; } const pure = (a, b) => { return a + b; }
  • 11.
  • 12.
    State is Read-Only lethasChanged = false; const nextState = {}; for (let i = 0; i < finalReducerKeys.length; i++) { const key = finalReducerKeys[i]; const reducer = finalReducers[key]; const previousStateForKey = state[key]; const nextStateForKey = reducer(previousStateForKey, action); if (typeof nextStateForKey === 'undefined') { const errorMessage = getUndefinedStateErrorMessage(key, action); throw new Error(errorMessage); } nextState[key] = nextStateForKey; hasChanged = hasChanged || nextStateForKey !== previousStateForKey; } return hasChanged ? nextState : state; Gera um novo estado a partir dos dados retornados pelo reducer Compara a referência em memória do novo estado com o estado anterior Retorna o novo estado caso seja um novo objeto
  • 13.
    Reducer function reducer(state =initialState, action) { switch (action.type) { case 'ADD_COUNTER': return { ...state, counter: state.counter + action.value }; case SUB_COUNTER': return { ...state, counter: state.counter - action.value }; default: return state; } } ...state = { counter: 0, savedCounters: [] }
  • 14.
    DATA FLOW ACTION REDUCERSTORE VIEW DISPATCH
  • 15.
    LIBS & STUFF REACT Renderizaçãode componentes REACT-DOM render – manipulação do DOM REDUX Core, util para configurações da store e separação de contextos dos reducers REACT-REDUX Utilizada para conectar componentes React na store BABEL Responsável por transpilar es6 para es5
  • 16.
    Reducer /Action const mapDispatchToProps =(dispatch) => ({ addCounter() { dispatch({ type: 'ADD_COUNTER', value: 1 }) } }); const initialState = { counter: 0 }; function counterReducer(state = initialState, action) { switch(action.type) { case 'ADD_COUNTER': return { ...state, counter: state.counter + action.value }; default: return state; } }
  • 17.
    Store & Middleware import *as Redux from 'redux'; import createLogger from 'redux-logger'; import reducer from './modules/reducer'; const middlewares = [ createLogger() ]; export default function configureStore() { return Redux.createStore( reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), Redux.applyMiddleware(...middlewares) ); }
  • 18.
    Rendering ReactDOM.render( <ReactRedux.Provider store={ reduxStore}> <AppContainer /> </ReactRedux.Provider>, document.getElementById('root'), );
  • 19.
    Container component class AppContainer extendsReact.Component { render() { return ( <App { ...this.props } /> ); } } const mapStateToProps = (state) => { return ( state ); } const mapDispatchToProps = (dispatch) => ({ addCounter() { dispatch({ type: 'ADD_COUNTER', value: 1 }) } }) const AppContainer = ReactRedux.connect( mapStateToProps, mapDispatchToProps)(AppContainer);
  • 20.
    Presentional component / View const App= (props) => { return ( <div> <div>{ props.counter }</div> <button onClick={() => props.addCounter() } > ADD </button> </div> ); }
  • 21.
  • 22.
    REDUX DEVTOOLS Time travel,TreeState chart 1
  • 23.

Notas do Editor

  • #13 Questionar: pq tem que ser read-only (interagir). 1 – Usando funções puras garantimos a integridade da estrutura do objeto e dessa forma o Redux compara referências em memória (ponteiros) dos objetos do estado anterior x novo estado, sendo mais performático do que comparar todas as propriedades novamente.
  • #14 *O Spread retorna um novo objeto/estado e não uma mutação do objeto anterior!
  • #17 A partir dos Reducers, podemos criar a Store, fonte de todos os dados da aplicação
  • #18 Armazenar o estado da Aplicação, permitir o acesso a esse estado e juntar todos os Reducers A
  • #19 Renderiza o componente definindo sua integração com a Store que foi criada
  • #20 Responsável por mapar os dados da Store (mapStatetoProps) e com base nesses dados é possível realizar Dispatches para atualizar a Store (mapDispatchToProps). ReactRedux.connect conecta o componente com a Store e disponibiliza os dados para a aplicação e permite update da Store via Dispatch.
  • #21 Apenas rendering, embora possa ter um estado isolado, independente da Store desde que este estado não influencie diretamente na aplicação como um todo. Ex. estados de UI