Flux

An Architecture for (not only) React

Oliver Zeigermann / @DJCordhose

Online version at: http://bit.ly/1AS7bQz

Oliver Zeigermann

What are React and Flux?

  • React is a "JavaScript libarary for building user interfaces"
  • Facebook and Instagram have been built using React
  • Flux is an architecture for React developed and used by Facebook
  • Objective is to make applications maintainable and easy to understand
  • Ideas found in Flux can not only be applied to React Web Applications
  • Companies using React and a Flux-architecture include Dow Jones, Facebook, Yahoo, and Netflix

Contents

  1. Frontend Architecture: Why?
  2. React in a nut shell
  3. Introduction to the core ideas of Flux
  4. A Sample Implementation: Yahoo's Fluxible
  5. FAQ
  6. Questions and discussion

1. Why Frontend Architecture?

Classic Server Side Rendering (Blue: Server, Violet: Browser)

  • Classic Web Application
  • each interaction triggers a new request and rendering on the server
  • All business logic on Server
  • Optionally some client side tweaks using JavaScript

Copyright 2015, Oliver Zeigermann

SPA: Sample Scenario for high need of good architecture

  • Single Page Application
  • a single HTML pages gets loaded containing all HTML and JavaScript
  • Rendering entirely in Browser
  • Business logic in browser allows for offline support

Copyright 2015, Oliver Zeigermann

Why Frontend Architecture in the first place?

  • Even when frontend does not live as long as the backend
    • you still spend more time reading the code than writing it
  • your aim should be to have the code as clear and easy to understand as possible, because
    • velocity still degrades when people have a hard time understanding the code
    • bug fixing and enhancements are easier when you can clearly tell which part of the code affects what part of the application
  • your code should follow a common architectural understanding, because
    • onboarding of new people still is easier if the application is clearly structured
    • shared code-ownership is easier if every module has the same design

Why is Frontend Architecture for an SPA hard to get right?

  • Not as much experience with frontend architecture as with backend
    • Traditionally, frontend code has not been engineered with maintainability in mind
    • Data and control flow in frontend does not play well with layers
  • All code is loaded into the browser at runtime
    • How do you structure that code to keep it maintainable?
    • How do the components of the system play together in the browser?
    • Initialization phases become much more complex
  • All rendering and interaction is done in the browser
    • How do you render in the browser in the first place?
    • How do you make it fast enough?
    • Communication with server requires asynchronous code

2. React in a nut shell

http://facebook.github.io/react/

https://github.com/facebook/react

Core Concepts

  • Based on components, holding both view and logic
  • Reactive one-way data-binding: Changes to state will be rendered automatically
  • Templates can be written in pure JavaScript or using the JSX template language
  • Can render both on server and on client side
  • ES6 (next JavaScript version) syntax recommended and supported
  • Babel to translate ES6 and JSX to standard ES5

Hello World React

class HelloMessage extends React.Component {
    render() {
        return (

{this.state.greeting}, World

); } constructor(props) { super(props); this.state = {greeting: this.props.greeting}; } updateModel(event) { this.setState({greeting: event.target.value}); } reset() { this.setState({greeting: ""}); } } var mountNode = document.getElementById('example'); React.render(<HelloMessage greeting="Hello" />, mountNode);
Run

3. Flux - An Architecture (not only) for React

  • Not a framework, but a set of architectural ideas
  • Born at Facebook to bring structure into their complex application
  • Core idea is a unidirectional flow of control
  • Objectives of architecture
    • Suitable for interactive applications (not only in the browser)
    • Guideline how to structure your complete application when it grows
    • Make clear how data and control flow through the system
    • What depends on what? What uses what?

Overview

Copyright 2015, Facebook, http://facebook.github.io/flux/docs/overview.html

Dispatcher

  • Singleton
  • Dispatches Actions to registered stores
  • All stores register to dispatcher
  • Can synchronize actions
    • to allow at most one active action per time
    • might be necessary to still understand application

Overview

Copyright 2015, Facebook, http://facebook.github.io/flux/docs/overview.html

Actions

  • Contain at least a symbol of what is the intention of the action
  • Can be as basic as a pure string
  • Often contains some payload
  • Can also be implemented as a function or an object
  • Can contain logic and also server communication

Overview

Copyright 2015, Facebook, http://facebook.github.io/flux/docs/overview.html

Stores

  • Hold the state and data of an application
  • Many times making the state of a component obsolete
  • Register to Dispatcher to listen for actions
  • Update themselves in response to actions
  • Fire events when they are updated
  • Components working as Controller Views listen to changes in them
  • More than one component can listen to a store
  • In a real world app, there would be many stores

Overview

Copyright 2015, Facebook, http://facebook.github.io/flux/docs/overview.html

Controller Views

  • A React component
  • Top-Level component
  • Creates and dispatches actions in response to user interaction
  • Passes callbacks to child views to execute logic
  • Listens to updates from stores
  • Propagates changes from stores to child views

Child Views

  • A React component
  • Just really dumb views
  • Can contain listeners, but those just unwrap events and call logic in Controller Views
  • Do not create actions
  • Do not listen to stores
  • Receive data and callbacks as properties from Controller Views

Summary

Copyright 2015, Facebook, http://facebook.github.io/flux/docs/overview.html

4. A Sample Implementation: Yahoo's Fluxible

  • Fluxible: Flux @Yahoo
  • Flux concept turned into a framework
  • Adds a router component
  • Buzz word: isomorphic JavaScript: can render on server and on client using the same code
  • Works very well with ES6, Babel translator, Gulp and Webpack

Transforming `Hello World` to a Controller View: The origin

class HelloMessage extends React.Component {
    render() {
        return (

{this.state.greeting}, World

); } constructor(props) { super(props); this.state = {greeting: this.props.greeting}; } updateModel(event) { this.setState({greeting: event.target.value}); } reset() { this.setState({greeting: ""}); } } var mountNode = document.getElementById('example'); React.render(<HelloMessage greeting="Hello" />, mountNode);

Step 1: Replacing component state with properties

class HelloMessage extends React.Component {
    render() {
        return (
// `this.state.greeting` turns `this.props.greeting`

{this.props.greeting}, World

); } updateModel(event) { // What do we do here??? // this.setState({greeting: event.target.value}); } reset() { // What do we do here??? // this.setState({greeting: ""}); } }

Step 2: Sending actions to change state

// close to what is called action creator in Flux notation
const messageAction = (actionContext, messagePayload) => {
    actionContext.dispatch('MESSAGE_ACTION', messagePayload);
}
class HelloMessage extends React.Component {
    render() {
      // unchanged
    }
    reset() {
        this.context.executeAction(messageAction, '');
    }
    updateModel(event) {
        this.context.executeAction(messageAction, event.target.value);
    }
}

Step 3: Handling actions in Store

class MessageStore extends BaseStore {
    static get storeName() {
        return 'MessageStore';
    }
    static get handlers() {
        return {
            'MESSAGE_ACTION': 'handleMessage'
        };
    }
    handleMessage(payload) {
        this._message = payload;
        this.emitChange();
    }
    get message() {
        return this._message;
    }
}

Step 4: Connecting View to Store

// causes a re-rendering of component `HelloMessage`
// when one of the stores calls `this.emitChange()`
connectToStores(HelloMessage, [MessageStore], getStateFromStores);
// will be called to create props passed used for re-rendering
const getStateFromStores = (stores) => {
    return {
        greeting: stores.MessageStore.message
    };
});

Step 5: Controller View with Child Views

class HelloMessage extends React.Component {
    render() {
        return (
          
// child views <MessageDisplay message={this.props.greeting + ', World'}/> <ResetButton resetHandler={this.reset.bind(this)} />
); // rest unchanged }
class MessageDisplay extends React.Component {
    render() {
        return 

{this.props.message}

; } }
class ResetButton extends React.Component {
    render() {
        return (
            
        );
    }
}

Live Sample

Run

Routing

  • Provides a mapping from path/method to component (nothing too fancy)
  • Implemented as a Fluxible store
  • Triggered using a navigation action, URL as payload
  • Rendering of links using a dedicated React component (NavLink)
  • Fluxible Router

Isomorphic Rendering

  • React allows to render component on server (into HTML) and on client (into DOM)
  • SEO possible by rendering pages on server using same components
  • Fast first page impression is more challenging
    • requires rendering on server and making it interactive on client
    • React has a mechanism to attach listener on client side only (no unnecessary re-rendering)
    • Transferring state of stores works via serialization and rendering into HTML as well (Dehydration/Rehydration)
    • Subsequent actions or route changes are a bigger challenge
  • Bringing Flux to the server
  • Sample Code (start using `npm dev`)
  • Run

FAQ

  • Where does server communication happen?
    • Implementations differ
    • Some do it in actions, others in stores
    • Choose whatever fits you best
  • Is this really a flow? Controller Views are accessing stores...
    • Technically, views access stores, so yes, it does not flow in a cycle
    • What would be the point in not accessing stores from views?
    • It would be possible to push the state from store to controller views if you really want to

Wrap-Up

  • Flux comes as an architectural idea based around React
  • It forces you to think about architecture
  • Flux makes it easy to reason about flow of control and data and thus complex data changes
  • You manage your data in whatever way you see it fit in stores
  • On the downside Flux requires you to write more boilerplate code
  • There will be a Flux talk at W-JAX 2015 concentrating on the architecture rather than the concrete implementation

Thank you!

Questions / Discussion

Oliver Zeigermann / @DJCordhose

Bonus Material

Links / Where to go from there

Immutable data structures in Store