Thinking in REACT

What?

A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES

JUst the V in MVC: React makes no assumptions about the rest of your technology stack

one-way reactive data flow

Reusable UI components FTW

Hello World!

var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
);

A word about JSX

JavaScript syntax extension that looks similar to XML

REACT JSX TRANSFORM

XML like syntax -> Plain Javascript

// JSX
ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
);

// PLAIN JAVASCRIPT TRANSFORMED
ReactDOM.render(React.createElement(
  'h1',
  null,
  'Hello, world!'
), document.getElementById('example'));

Attribute Expressions

var person = <Person 
    name={window.isLoggedIn ? window.name : ''} 
/>;

Attributes

var input = <input type="button" disabled={true} />;

var abs_shape = <div style={{
    position: "absolute",
    width: "100%",
    height: "100%",
    backgroundColor: this.state.beverage.color,
}}>;

Child Expressions

var content = <Container>
    {window.isLoggedIn ? <Nav /> : <Login />}
</Container>;

A more complex component

Introducing React classes

var React = require('react');
var ReactDOM = require('react-dom');

var MyComponent = React.createClass({
    render: function(){
        return (
            <h1>Hello, world! I am a new Component!</h1>
        );
    }
});

ReactDOM.render(
    <MyComponent/>,
    document.getElementById('example')
);

With ES2015

import React from 'react';

class MyComponent extends React.Component {
    render() {
        return (
            <h1>Hello, world! I am a new Component!</h1>
        );
    }
}

ReactDOM.render(
    <MyComponent/>,
    document.getElementById('example')
);

Lifecycle

componentWillMount – Invoked once before rendering occurs
 

componentDidMount – Invoked once, after rendering occurs
 

shouldComponentUpdate – Return value determines whether component should update
 

componentWillUnmount – Invoked prior to unmounting component

SPECS

getInitialState – Return value is the initial value for state

 

getDefaultProps – Sets fallback props values if props aren’t supplied

 

mixins – An array of objects, used to extend the current component’s functionality

The State

class BeerBox extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      name: '',
      abv: 0,
      origin: '',
      ok: false
    };
  }

  loadBeerFromServer() {
    setTimeout(() => {
      this.setState(
        {
          name: 'Guinness',
          abv: 5,
          origin: 'Ireland',
          ok: true
        }
      );
    }, 2000);
  }

  componentDidMount() {
    this.loadBeerFromServer();
  }

  //...
};

MIXINS

var SetIntervalMixin = {
  componentWillMount: function() {
    this.intervals = [];
  },
  setInterval: function() {
    this.intervals.push(setInterval.apply(null, arguments));
  },
  componentWillUnmount: function() {
    this.intervals.forEach(clearInterval);
  }
};
var TickTock = React.createClass({
  mixins: [SetIntervalMixin], // Use the mixin
  getInitialState: function() {
    return {seconds: 0};
  },
  componentDidMount: function() {
    this.setInterval(this.tick, 1000);
  },
  tick: function() {
    this.setState({seconds: this.state.seconds + 1});
  },
  render: function() {
    return (
      <p>
        React has been running {this.state.seconds} s.
      </p>
    );
  }
});

LIVE DEMO! 

https://github.com/DjangoBeer/reactjs-samples/tree/master/lifecycle

Thinking in React

SearchBar

BeerTable

BeerRow

BeerOriginRow

BeerSearchBox

Start From the smaller components

import React from 'react';


class BeerOriginRow extends React.Component {
  render() {
    return (
      <tr><th colSpan="2">{this.props.origin}</th></tr>
    );
  }
};

export default BeerOriginRow;
import React from 'react';


class BeerRow extends React.Component {
  render() {
    return (
      <tr>
        <td>{this.props.beer.name}</td>
        <td>{this.props.beer.abv}%</td>
      </tr>
    );
  }
};

export default BeerRow;

Who uses these components?

class BeerTable extends React.Component {
  render() {
    var rows = [];
    var lastOrigin = null;
    this.props.beers.forEach(beer => {
      if (beer.name.toLowerCase()
          .indexOf(this.props.filterText.toLowerCase()) === -1) {
        return;
      }
      if (beer.origin !== lastOrigin) {
        rows.push(
          <BeerOriginRow origin={beer.origin} key={beer.origin} />
        );
      }
      rows.push(<BeerRow beer={beer} key={beer.name} />);
      lastOrigin = beer.origin;
    });
    return (
      <table>
        //...
        <tbody>{rows}</tbody>
      </table>
    );
  }
};

BeerTable receives a list of beers and a query, then it renders everything

We need a SearchBox able to trigger an event on text change! Pass it a callback!

class SearchBar extends React.Component {
  handleChange() {
    this.props.onUserInput(
      React.findDOMNode(this.refs.filterTextInput).value
    );
  }
  render() {
    return (
      <form>
        <input
          type="text"
          placeholder="Search..."
          value={this.props.filterText}
          ref="filterTextInput"
          onChange={this.handleChange.bind(this)} />
      </form>
    );
  }
};


export default SearchBar;

Put it all Together!

class BeerSearchBox extends React.Component {

  // ....

  handleUserInput (filterText) {
    this.setState({
      filterText: filterText,
    });
  }

  render() {
    return (
      <div>
        <SearchBar onUserInput={this.handleUserInput.bind(this)}/>
        <BeerTable filterText={this.state.filterText} beers={this.state.beers}/>
      </div>
    )
  }
};

Live DEMO!!!

https://github.com/DjangoBeer/reactjs-samples/tree/master/beersearch

A word about Touchstone.js

Live DEMO!!!

https://github.com/astagi/cincin

More in REACT.js World

Server-side RENDERING

Faster Page LOADS

By rendering on the server, you get to send down a complete webpage, cut out an HTTP request

More reliable SEO

Any crawler that navigates to your site will see a complete page filled with content, rather than an empty page that requires JavaScript execution.

Flux

Flux is an architecture that Facebook uses internally when working with React. It is not a framework or a library. It is simply a new kind of architecture that complements React and the concept of Unidirectional Data Flow.

React Native

// iOS

var React = require('react-native');
var { TabBarIOS, NavigatorIOS } = React;

var App = React.createClass({
  render: function() {
    return (
      <TabBarIOS>
        <TabBarIOS.Item title="React Native" selected={true}>
          <NavigatorIOS initialRoute={{ title: 'React Native' }} />
        </TabBarIOS.Item>
      </TabBarIOS>
    );
  },
});
// Android

var React = require('react-native');
var { DrawerLayoutAndroid, ProgressBarAndroid } = React;

var App = React.createClass({
  render: function() {
    return (
      <DrawerLayoutAndroid
        renderNavigationView={() => <Text>React Native</Text>}>
        <ProgressBarAndroid />
      </DrawerLayoutAndroid>
    );
  },
});

Conclusions

EMAil: a.stagi@nephila.it
Twitter: @4stagi
Github: @astagi

Thinking in React

By Andrea Stagi

Thinking in React

My dip into the React.js world

  • 2,274