Top Banner
© 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD http://www.rocksolidknowledge.com Managing Data in an SPA using the Flux Pattern
31

KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

Feb 12, 2018

Download

Documents

vuthu
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 1

RoCkKnOwledge

SOLiD

http://www.rocksolidknowledge.com

Managing Data in an SPA using the Flux Pattern

Page 2: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 2

Motivation

2-way data binding can lead to complex and unpredictable data flows

Leads to sluggish UI

Leads to code that is difficult to reason about and debug

Page 3: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 3

Solution

React

UI framework

Better performance

Encourages uni-directional data flows

Flux

Uni-directional data flow pattern

Page 4: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 4

React

Component-based

JSX

Virtual DOM

Promotes uni-directional data flow

Page 5: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 5

Component definition & JSX

import * as React from 'react'

export class MyComponent extends React.Component<any, any> {render() { return (<div>

<span id="foo" className="bar">Hello from React</span></div>

)};};

React.createElement(

"div",

null,

React.createElement(

"span",

{ id: "foo", className: "bar" },

"Hello from React"));

Page 6: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 6

Composition

import * as React from 'react'import {Header} from './components/Header'import {Footer} from './components/Footer'

export class App extends React.Component<any, any> {render() { return<div><Header>A header</Header><span id="foo" className="bar">Hello from React</span><Footer someFooterAttribute="someValue">A footer</Footer>

</div>};

};

Page 7: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 7

Demo

React ‘hello world’

Page 8: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 8

Client-side routing

React router

Declarative, nested routes

Default route

Not found route etc

Route parameters

Links

Programmatic redirect

Page 9: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 9

Client-side route configuration

import * as React from 'react'import {BrowserRouter as Router, Route} from 'react-router-dom'import {List} from './ListController'import {Details} from './DetailsController'

export class App extends React.Component<any, any> {render() { return (<Router><div><Route path="/" exact component={ListController}/><Route path="/:id" component={DetailsController}/>

</div></Router>

)};};

Page 10: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 10

Demo

Client-side routing with React router

Page 11: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 11

Props v State

Properties (props)

Like HTML attributes

Passed down by parent

Immutable

State

Mutable

Page 12: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 12

Promoting ‘one way data flow’

Often state becomes props

‘Smart’ components at top of component hierarchy acquire all the state that is needed

State converted to properties passed down through the hierarchy to ‘dumb’ components

Page 13: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 13

Smart component

import * as React from 'react'import {Meeting} from '../api/Meeting'import {getMeetings} from '../api/MeetingFunctions'import {List} from './List'

interface IListControllerState {meetings: Meeting[];

};export class ListController extends React.Component<any,

IListControllerState> {constructor() {super();this.state = {meetings: getMeetings()};

}render() { return (<List meetings={this.state.meetings} />

)};};

Page 14: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 14

Dumb component

import * as React from 'react'import {Meeting} from '../api/Meeting'import {Link} from 'react-router-dom'

interface IListProps {meetings: Meeting[];

};

const CreateRow = (meeting: Meeting)=>{return ( <li key={meeting.Id}><Link to={"/"+meeting.Id}>{meeting.Title}</Link>

</li>)

};export let List = (props:IListProps)=><ul>{props.meetings.map(CreateRow)}</ul>

Page 15: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 15

Demo

Smart and dumb components

Page 16: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 16

Smart/dumb component interaction

Dumb components often need their properties to change

But their properties are immutable

Smart components pass event handlers to dumb components

Dumb components fire events upwards

Smart components handle, change their state and re-render dumb components with new props

Event handlers passed as far down hierarchy as needed

Page 17: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 17

Smart component

interface IDetailsControllerState {meeting: Meeting;

};export class DetailsController extendsReact.Component<RouteComponentProps<any>, IDetailsControllerState> {constructor(props: RouteComponentProps<any>) {super(props);this.state = {meeting: getMeeting(+this.props.match.params.id)};

};onChange(event: React.ChangeEvent<any>){var title = event.target.value;this.setState({meeting: {Id: this.state.meeting.Id, Title: title}});

}; render() { return (<Details meeting={this.state.meeting}

onChange={this.onChange.bind(this)} />)};

};

Page 18: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 18

Dumb component

interface IDetailsProps {meeting: Meeting;onChange: (event: React.ChangeEvent<any>)=>void;

};

export let Details = (props: IDetailsProps) =><div>…<input id="title" value={props.meeting.Title}

onChange={props.onChange}/>…

</div>

Page 19: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 19

Demo

Smart/dumb component interaction

Page 20: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 20

Flux

Uni-directional data flow pattern

Many implementations

E.g. Flux, Redux, …

User interactions create actions

Actions dispatched to stores

Stores update and notify UI

Page 21: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 21

Uni-directional data flow

Action creator

UIDispatcher

Store

5. query

4. notify

3. dispatch

1

2

Page 22: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 22

Store

import {EventEmitter} from "events";

class MeetingFluxStoreImpl extends EventEmitter {putMeetings(meetings: Meeting[]) {// save meetingsthis.emit("meeting-flux-store-change";)

};get meetings(): Meeting[] {// return saved meetings

};

// putMeeting & deleteMeeting methods

addChangeListener(callback:()=>void) {this.on(this.changeEvent, callback);

};removeChangeListener(callback:()=>void) {this.removeListener(this.changeEvent, callback);

};};export let MeetingFluxStore = new MeetingFluxStoreImpl();

Page 23: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 23

Actions

export enum ActionType {PutMeetings,PutMeeting,DeleteMeeting

};

export interface Action<T> {type: ActionType;payload?: T;

};

Page 24: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 24

Action creators

import {Meeting} from "../api/Meeting";import {ActionType} from "./ActionTypes";

export function putMeetings(meetings: Meeting[]) {return {type: ActionType.PutMeetings, payload: meetings};

};

export function putMeeting(meeting: Meeting) {return {type: ActionType.PutMeeting, payload: meeting};

};

export function deleteMeeting(id: number) {return {type: ActionType.DeleteMeeting, payload: id};

};

Page 25: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 25

Flux dispatcher

import {Dispatcher} from 'flux';

export let AppDispatcher = new Dispatcher();

Page 26: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 26

Acquiring state & dispatching actions

import {AppDispatcher} from "../dispatcher/Dispatcher";import {putMeetings} from "../api/MeetingFunctions";

export function loadMeetings() {const meetings = getMeetings();AppDispatcher.dispatch(putMeetings(meetings));

};

Page 27: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 27

Handling dispatched actions

import {AppDispatcher} from "../dispatcher/Dispatcher";import {ActionType, Action} from "../actions/ActionTypes";import {MeetingFluxStore} from "../stores/MeetingFluxStore";

export function initDispatcherListener() {AppDispatcher.register((action: Action<any>)=>{switch(action.type) {case ActionType.PutMeetings:MeetingFluxStore.putMeetings(action.payload);break;

case ActionType.PutMeeting:MeetingFluxStore.putMeeting(action.payload);break;

case ActionType.DeleteMeeting:MeetingFluxStore.deleteMeeting(action.payload);break;

default:break;

}});

};

Page 28: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 28

Wiring up the dispatcher listener

import { loadMeetings } from "./actions/MeetingFunctions";import { initDispatcherListener } from"../stores/DispatcherListener";

initDispatcherListener();loadMeetings();render( <App/>, document.getElementById("app"));

Page 29: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 29

Smart component

import {MeetingFluxStore} from "../stores/MeetingFluxStore";

export class ListController extendsReact.Component<any, IListControllerState> {constructor() {super();this.state = {meetings: MeetingFluxStore.meetings};MeetingFluxStore.addChangeListener(this.handleUpdate);

};componentWillUnmount() {MeetingFluxStore.removeChangeListener(this. handleUpdate);

};private onUpdate() {this.setState({meetings: MeetingFluxStore.meetings});

};private handleUpdate = this.onUpdate.bind(this));render() { return <MeetingList meetings={this.state.meetings} /> };

};

Page 30: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 30

Demo

Flux

Page 31: KnOwledge RoCk SOLiD - SDD Conferencesddconf.com/brands/sdd/library/react-flux.pdf · © 2017 RoCk SOLid KnOwledge 1 RoCk KnOwledge SOLiD ... © 2017 RoCk SOLid KnOwledge 23 Actions

© 2017 RoCk SOLid KnOwledge 31

Summary

2-way data binding can lead to complex and unpredictable data flows

React & Flux enforce a uni-directional data flow pattern

Redux & Reselect also worth look