A tour on the 
React ecosystem

Carlos Guedes - 2015/12/02

Carlos Guedes

Sky Uk Limited (we are hiring!)

Toptal

Software Engineer
+10 year experience in Web
Former teacher at ISEL

This is all about JavaScript 

Churn In the JavaScript World (Jul14) 

In the news*

* Thoughtworks' Technology Radar

JavaScript Settles to Merly Chaotic (Nov15)

  • Grew a lot in the past years
  • Now has a sustainable and open plan (TC39)

Growth

  • @1999 - ES3
  • @2011 - ES5
  • @2015 - ES6 (JavaScript 2015)
  • @2016 - ES7 (JavaScript 2016)
  • @2017 - ES8 ...

Language Improvements (ES6)

Spread Operator and Rest Parameters

[1, 2, ...[3, 4, 5], 6, 7]
Arrow Functions
[1, 2].map(v => v * 2)
Assignment Destructuring
let { id, title } = this.props.album
Template literals
text = `Album ${title} contains ...`
Object literals
let obj = { foo, [key]: value, fn() {} }
Classes
class Todo extends Component { 
}
var
let
const
Symbols
const symbol = Symbol('some desc')
Iterators
Generators
Promises
Maps WeakMaps
Sets WeakSets
Proxies
Reflection
Modules
export const foo = 'bar'
import { render } from 'react-dom'
  • Module bundlers (​Webpack, Browserify)
  • Transpilers are our new friends
    • JavaScript to JavaScript
    • Babel is King

Tools & Techniques

  • Hot Reload / BrowserSync
  • Universal / isomorphic apps
  • Local CSS
  • StandardJS, ESLint
  • Developer Tools (Chrome, Firefox, ...)
  • ...

React

UI = f(data)​

every time data changes, UI is re-rendered*

const { Component } = React

class Click extends Component {
  constructor() {
    super()
    this.state = { counter: 2 }
  }

  handleClick() {
    this.setState({ counter: this.state.counter + 1 })
  }

  render() {
    const { counter } = this.state
    return (
      <a onClick={_ => this.handleClick()}>
        You have clicked <strong>{counter}</strong> times.
      </a>
    )
  }
}

ReactDOM.render(
  <Click />,
  document.querySelector('#root')
)

Click component

Reconciliation

React's key design decision is to make the API seem like it re-renders the whole app on every update.

renderA: <div style={{color: 'red'}} />
renderB: <div style={{fontWeight: 'bold'}} />
=> [removeStyle color], [addStyle font-weight 'bold']
O(n^3)
O(n3)O(n^3)
O(n^2)
O(n2)O(n^2)

heuristics

n = 100          1.000.000                                        10.000  

Demo

class Todo extends React.Component {
  static propType = {
   text: React.PropTypes.string.isRequired,
   completed: React.PropTypes.boolean,
   onToggle: React.PropTypes.func 
  }
  render() {
    const { text, completed, onToggle } = this.props
    return (
     <li onClick={onToggle}
         style={{
          textDecoration: completed
            ? 'line-through'
            : 'none'
         }}
     >
      {text}
     </li>
  )
}

Todo component

const Component = (props) => <ui />
React 0.14

Stateless Functions

const Todo = ({
  text, completed,
  onToggle, 
}) => (
  <li onClick={onToggle}
      style={{
       textDecoration: completed
         ? 'line-through'
         : 'none'
      }}
  >
    {text}
  </li>
)

Stateless - Todo component

  <Todo text='Hey'  
        completed={false}
        onToggle={...} />

Demo

React

is for the view

Where is stored the application state?

State is managed by stores

... all the "fluxes"

Unidirectional flow

Flux architecture

They have got a lot of (recurring) problems in the past with bidirectional flow

flux

reflux

redux

fluxxor

by Dan Abramov
(gaearon)

by Facebook

Store implementations

...ux...

redux

$ npm install redux react-redux

Three principles

  1. Single source of truth
  2. State is readonly
  3. Mutations are written as pure functions

You need to know

  • redux is not tied to react
  • react-redux binds redux to react
    • ng-redux; ng2-redux; redux-falcor; ...
  • redux was written to support hot reload

They have made a cartoon!

redux is for data

like
react is for UI

state = f(state, action)

state = f(state, action)

  • Predictability
  • no side-effects
  • hot-reload
  • time-machine
  • f is a reducer

state = f(state, action)

// Counter reducer
function counter(state = 0, action) {
  switch(action.type) {
    case 'INCREMENT_COUNTER':
      return state + 1
    case 'DECREMENT_COUNTER':
      return state - 1
  }
  return state
}
const store = createStore(counter)

// Action dispatching and store state
const before = store.getState()
store.dispatch({ type: 'INCREMENT_COUNTER' })

const after = store.getState()
expect(after).toEquals(before + 1)

Demo

Application

Demos

Counter

Todo

API Explorer

const { createStore } = Redux
function counter(state = 0, action) {
  switch(action.type) {
    case 'INCREMENT_COUNTER':
      return state + 1
    case 'DECREMENT_COUNTER':
      return state - 1
  }
  return state
}

const store = createStore(counter)
store.dispatch({ type: 'INCREMENT_COUNTER' })

class App extends React.Component {
  render() {
    return (
      <Counter value={store.getState()} />
    )
  }
}

const Counter = ({value}) => <div>Counter: {value}</div>

function render() {
  ReactDOM.render(
    <App />,
    document.querySelector('#root')
  )
}
render()

store.subscribe(render)
store.dispatch({ type: 'INCREMENT_COUNTER' })
store.dispatch({ type: 'INCREMENT_COUNTER' })

React libs

react-router

$ npm install react-router
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Link } from 'react-router'

const App = React.createClass({/*...*/})
...

render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        {/* add some nested routes where we want the UI to nest */}
        {/* render the stats page when at `/inbox` */}
        <IndexRoute component={InboxStats}/>
        {/* render the message component at /inbox/messages/123 */}
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)
import React from 'react'
import { Link } from 'react-router'

...

  <div>
    <h1>Messages</h1>
    <div className="master">
      <ul>
        {this.props.messages.map(msg => (
          <li key={msg.id}><Link to={`/inbox/messages/${msg.id}`}>{msg.subject}</Link></li>
        ))}
      </ul>
    </div>
  </div>

DEMO

react-router

react-boostrap

$ npm install react-bootstrap
const NavDropdownExample = React.createClass({
  handleSelect(event, selectedKey) {
    event.preventDefault();
    alert('selected ' + selectedKey);
  },
  render() {
    return (
      <Nav bsStyle="tabs" activeKey={1} onSelect={this.handleSelect}>
        <NavItem eventKey={1} href="/home">NavItem 1 content</NavItem>
        <NavItem eventKey={2} title="Item">NavItem 2 content</NavItem>
        <NavItem eventKey={3} disabled>NavItem 3 content</NavItem>
        <NavDropdown eventKey={4} title="Dropdown" id="nav-dropdown">
          <MenuItem eventKey="4.1">Action</MenuItem>
          <MenuItem eventKey="4.2">Another action</MenuItem>
          <MenuItem divider />
          <MenuItem eventKey="4.4">Separated link</MenuItem>
        </NavDropdown>
      </Nav>
    );
  }
});
ReactDOM.render(<NavDropdownExample />, mountNode);

React-Bootstrap is a library of reuseable front-end components. You'll get the look-and-feel of Twitter Bootstrap, but with much cleaner code, via Facebook's React.js framework.

const modalInstance = (
  <div className="static-modal">
    <Modal.Dialog>
      <Modal.Header>
        <Modal.Title>Modal title</Modal.Title>
      </Modal.Header>

      <Modal.Body>
        One fine body...
      </Modal.Body>

      <Modal.Footer>
        <Button>Close</Button>
        <Button bsStyle="primary">Save changes</Button>
      </Modal.Footer>

    </Modal.Dialog>
  </div>
);

ReactDOM.render(modalInstance, mountNode);

DEMO

react-bootstrap

React

Native 

 

  • Distinct technology stacks
  • Cannot share nothing
  • Iteration speed gets lower
  • Gets harder to scale teams

Why

"Learn once, write anywhere"

"Write once, run anywhere"

"Write once, run anywhere"

How

React Native is focused on changing the way view code is written. For the rest, we look to the web for universal standards and polyfill those APIs where appropriate.

How

Web got it!

  • Distinct technology stacks
  • We cannot share nothing
  • Iteration speed gets lower
  • Gets harder to scale team
  • HTML, CSS, JS
  • Some code and tech
  • F5 reload / hot-reload
  • React!

Is it fast?

reconciliation

batch updates

async and native updates

60 fps

The flow

The flow

Demo

Q&A

Tnks for your time!

Made with Slides.com