Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Let's Redux!

5,597 views

Published on


Let's Redux! by Joseph Chiang
Published April 15, 2016 in Technology

For people who use React but haven’t tried Redux.
- Why - Common issues while people use React
- Redux Basic Concept

Published in: Technology
  • Be the first to comment

Let's Redux!

  1. 1. Let’s Redux for people who use React but haven’t tried Redux @josephj6802
  2. 2. React.js is Awesome Building a complicate UI was never so easy Plugins Dashboard Widget Composer ACL Term Languages
  3. 3. 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
  4. 4. 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…”
  5. 5. Code Smells • Delegation is difficult • Top-down props • Mixed concerns • View logic • Data fetching • Data decoration • Poor state management • Component-specific • Mutable • Not maintainable <WidgetsEdit/> Top-level Component 1469 lines in total!!
  6. 6. 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 ( <ButtonNavList {...manyStates}> <ButtonNavItem {...manyStates}/> </ButtonNavList> <StylePreview {...manyStates}/> <CodeEditor {...manyStates}/> ) } } who takes care of everything for childs Preparing data, passing props, handling events for childs
  7. 7. 22 Event Handlers Child passes all events to its parent because only the top-level component should access state Handling Children Events
  8. 8. Delegation or Not? If your think NO, plz put inside… • Pass all <ButtonNavItem/> required props to <ButtonNavList/> • Handle its events in <ButtonNavList/> • Handle its events in <WidgetsEdit/> If your think YES, plz keep there… Handle child logic in top-level component. Both ways are not good… Not Convenient Dirty! Should <ButtonNavItem/> appear in top-level as illustrated?
  9. 9. Fetching Data for Childs No Separation of Concerns
  10. 10. Why Redux? Not have children? https://github.com/reactjs/redux/issues/151#issuecomment-173749456
  11. 11. 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
  12. 12. Basic Concept 1. Action 2. Reducer 3. State https://github.com/reactjs/redux/issues/151#issuecomment-134713785
  13. 13. 1. Action Pure Object { type: 'SORT_PLUGINS', by: 'id', direction: 'desc' } Minimum data which describes the change Only the “type” property is required
  14. 14. 1. Action
  15. 15. 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
  16. 16. 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
  17. 17. 2. Reducer reducer(prevState, action) => nextState
  18. 18. 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
  19. 19. 3. Store
  20. 20. 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
  21. 21. 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
  22. 22. Redux Data Flow Reducer Store ActionActionAction store = createStore(reducerFn); store.subscribe(eventHandlerFn); App store.dispatch(actionCreatorFn); reducerFn = (currentState, action) => nextState
  23. 23. Redux Data Flow Reducer Store ActionActionAction 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!
  24. 24. 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
  25. 25. 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 ( <ButtonNavList {...manyStates}> <ButtonNavItem {...manyStates}/> </ButtonNavList> <StylePreview {...manyStates}/> <CodeEditor {...manyStates}/> ) } } who takes care of everything of its child components Preparing data & handling events for child components
  26. 26. 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 ( <ButtonNavList> <ButtonNavItem/> <ButtonNavList> <StylePreview/> <CodeEditor/> ) } } WidgetsEdit = connect(mapStateToProps)(WidgetsEdit); who only cares about himself Delegation = Preparing data and dispatching for itself
  27. 27. 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 ( <a onClick={() => dispatch(modeSwitch('mobile'))}>/> Mobile View </a> <iframe src={url}/> ); } StylePreview = connect((state) => { // map state to props return { url: state.widget.url, } })(StylePreview); … And dispatches actions by itself
  28. 28. 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
  29. 29. Further Reading https://egghead.io/series/getting-started-with-redux egghead.io Very good material for learning Redux!
  30. 30. Discussion - Store Structure One Store - Could it possibly fit our application?
  31. 31. THANK YOU! Let’s Redux!!

×