Slide 1

Slide 1 text

Let’s Redux for people who use React but haven’t tried Redux @josephj6802

Slide 2

Slide 2 text

React.js is Awesome Building a complicate UI was never so easy Plugins Dashboard Widget Composer ACL Term Languages

Slide 3

Slide 3 text

Building a complicate UI was never so easy React.js is Awesome • Easy to learn • Manage State instead of DOM • One-way Data Flow Model • UI = fn(State) Advantages Absolutely a correct technical decision

Slide 4

Slide 4 text

PROBLEMS!! React doesn’t We don’t have a front-end application architecture. “It worked well with simple components, but as our interfaces become more complicate we soon found…”

Slide 5

Slide 5 text

Code Smells • Delegation is difficult • Top-down props • Mixed concerns • View logic • Data fetching • Data decoration • Poor state management • Component-specific • Mutable • Not maintainable Top-level Component 1469 lines in total!!

Slide 6

Slide 6 text

React.js = “Good” Parent class WidgetsEdit extends Component { constructor(props) { super(props); } componentWillMount() { $.ajax(...).then((...) => { // ... decorate data ... this.setState(...) }); } render() { let manyStates = that.state; // ... view logic ... return ( ) } } who takes care of everything for childs Preparing data, passing props, handling events for childs

Slide 7

Slide 7 text

22 Event Handlers Child passes all events to its parent because only the top-level component should access state Handling Children Events

Slide 8

Slide 8 text

Delegation or Not? If your think NO, plz put inside… • Pass all required props to • Handle its events in • Handle its events in If your think YES, plz keep there… Handle child logic in top-level component. Both ways are not good… Not Convenient Dirty! Should appear in top-level as illustrated?

Slide 9

Slide 9 text

Fetching Data for Childs No Separation of Concerns

Slide 10

Slide 10 text

Why Redux? Not have children? https://github.com/reactjs/redux/issues/151#issuecomment-173749456

Slide 11

Slide 11 text

Why Redux? Solve all the mentioned issues • Delegation is difficult easier • Top-down props including events is not required • Mixed Separation of concerns • View logic • Data fetching goes to ”Action” • Data decoration goes to “Reducer” • Poor Better state management • Component App-specific • Mutable Immutable • Not Maintainable

Slide 12

Slide 12 text

Basic Concept 1. Action 2. Reducer 3. State https://github.com/reactjs/redux/issues/151#issuecomment-134713785

Slide 13

Slide 13 text

1. Action Pure Object { type: 'SORT_PLUGINS', by: 'id', direction: 'desc' } Minimum data which describes the change Only the “type” property is required

Slide 14

Slide 14 text

1. Action

Slide 15

Slide 15 text

1-1. Action Creator Pure function which creates an action function sortPlugins(by, direction = 'desc') { return { type: 'SORT_PLUGINS', by, direction }; } Reusable, Portable, and Easy to Test (Return promise for asynchronous action) Make it easier to create an action

Slide 16

Slide 16 text

2. Reducer Pure function which returns the next state function reducer(state = {}, action) { switch (action.type) { case 'SORT_PLUGINS': return { ...state, plugins: { orderBy: action.by, orderByDirection: action.direction, data: _.sortByOrder(state.data, action.by, 
 action.direction) } }; default: return state; }; } reducer(previousState, action) => state Initial State Always return current state

Slide 17

Slide 17 text

2. Reducer reducer(prevState, action) => nextState

Slide 18

Slide 18 text

3. Store A plain object which holds application state { plugins: { data: [ {id: 1, name: 'AdRoll'}, {id: 2, name: 'Agile CRM'}, {id: 3, name: 'Brand Networks'} ], orderBy: 'id', orderByDirection: 'desc' } } Dispatching actions is the only way to update store Store is the only one state for the whole app

Slide 19

Slide 19 text

3. Store

Slide 20

Slide 20 text

3-1. Store Creation with Reducer (the spec of your store) store = createStore(reducer); import {createStore} from 'redux'; let store = createStore(reducer); The store provides several useful API methods

Slide 21

Slide 21 text

store.dispatch(sortPlugins('name', 'desc')); 3-2. Store APIs store#dispatch store#subscribe let currentValue; store.subscribe(() => { let previousValue = currentValue; currentValue = store.getState(); if (previousValue === currentValue) { return; } // DO SOMETHING... }); store#getState

Slide 22

Slide 22 text

Redux Data Flow Reducer Store Action Action Action store = createStore(reducerFn); store.subscribe(eventHandlerFn); App store.dispatch(actionCreatorFn); reducerFn = (currentState, action) => nextState

Slide 23

Slide 23 text

Redux Data Flow Reducer Store Action Action Action store = createStore(reducerFn); store.subscribe(eventHandlerFn); App store.dispatch(actionCreatorFn); reducerFn = (currentState, action) => nextState That’s it! • Super easy for both code and concept • Pure functions & objects w/o side-effects • Provides a better data flow for JS apps • Not just for React.js apps • jQuery or Node.js? No problem!

Slide 24

Slide 24 text

Redux and React? First, let’s check the list again • Delegation is easier • Top-down props is not required • Separation of concerns • View logic • Data fetching goes to ”Action” • Data decoration goes to “Reducer” • Better state management • App-specific • Immutable • Maintainable • Delegation is easier • Top-down props is not required

Slide 25

Slide 25 text

React.js = “Good” Parent class WidgetsEdit extends Component { constructor(props) { super(props); } componentWillMount() { $.ajax(...).then((...) => { // ... decorate data ... this.setState(...) }); } render() { let manyStates = that.state; // ... decorate state ... return ( ) } } who takes care of everything of its child components Preparing data & handling events for child components

Slide 26

Slide 26 text

React + Redux = Bad Parent import React, {Component} from 'react'; import {connect} from 'react-redux'; import {fetchData} from ‘./actions'; class WidgetsEdit extends Component { constructor(props) { super(props); } componentWillMount() { this.props.dispatch(fetchData()); } render() { return ( ) } } WidgetsEdit = connect(mapStateToProps)(WidgetsEdit); who only cares about himself Delegation = Preparing data and dispatching for itself

Slide 27

Slide 27 text

React.js w/ Redux Child component connects to store by itself import React from 'react'; import {connect} from 'react-redux'; import {modeSwitch} from './actions'; let StylePreview({url, dispatch} = props) => { return ( dispatch(modeSwitch('mobile'))}>/> Mobile View ); } StylePreview = connect((state) => { // map state to props return { url: state.widget.url, } })(StylePreview); … And dispatches actions by itself

Slide 28

Slide 28 text

Summary • Good start to learn functional programming • Add complexity but also add maintenance = worthy • Single Store • Time Travel (e.g. Undo) is possible • No need to access React state API anymore • Not only for React.js

Slide 29

Slide 29 text

Further Reading https://egghead.io/series/getting-started-with-redux egghead.io Very good material for learning Redux!

Slide 30

Slide 30 text

Discussion - Store Structure One Store - Could it possibly fit our application?

Slide 31

Slide 31 text

THANK YOU! Let’s Redux!!