REACT IN 60 minutes

CONCEPTS AND CODE

React

 A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES*

* React isn't an MVC framework.

WHY*

BUILD COMPOSABLE COMPONENTS

SIMPLE and DECLARATIVE

* Facebook's official reasons

LEARN ONCE, WRITE ANYWHERE

WHO USE

Pretty TIME TO START

REACT

IMPLEMENTS a GROUP OF IDEAS AND CONCEPTS

  • Virtual DOM
  • JSX syntax
  • ES6 support
  • Component driven development
  • Isomorphic React

virtual DOM

concept OF

VIRTUAL DOM

  1. Represent original DOM in memory
  2. Calculate diff with changed Virtual DOM
  3. Patch original DOM nodes

SoLVEs THE FOLLOWING TASKS

It is an abstraction of the real DOM

Virtual DOM. Diff Algorithm

1. React only tries to reconcile trees level by level.

Tree diff algorithm has O(n^3) complexity*

2. React introduce the key attribute to help the diff algorithm do matching

React approach

Turn a O(n^3) problem into a O(n) one.

REACT APROACH. Batched DOM operations

1. Whenever you set the state on a component, React will mark it as dirty.

2. The component rebuilds the virtual DOM for its children.

Sub-tree Rendering

Selective Sub-tree Rendering

React will optimize DOM mutation by using batching and change detection.

HOW WORK

With virtual DOM

var element = React.createElement('div', {
    className: 'reactElement'
}, 'Hello world');

ReactDOM.render(
    element, 
    document.getElementById('reactContainerElement')
);

React Elements

React.createElement = (type, props, children) => ReactElement;
ReactDOM.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;

Code example

API Definitions

Render result (on jsfiddle)

<div id="reactContainerElement">
    <div data-reactroot class="reactElement">Hello world</div>
</div>

Light, stateless, immutable, virtual representation of a DOM Element

var divFactory = React.createFactory('div');

var element = divFactory({
    className: 'reactElement'
}, 'Hello world');

ReactDOM.render(
    element, 
    document.getElementById('reactContainerElement')
);

REACT FACTORIES

Code example

Render result (on jsfiddle)

<div id="reactContainerElement">
    <div data-reactroot class="reactElement">Hello world</div>
</div>

A ReactElement-factory is simply a function that generates a ReactElement with a particular type property

var element = React.DOM.div({
    className: 'reactElement'
}, 'Hello world');

ReactDOM.render(
    element, 
    document.getElementById('reactContainerElement')
);

REACT.DOM

Code example

Render result (on jsfiddle)

<div id="reactContainerElement">
    <div data-reactroot class="reactElement">Hello world</div>
</div>

React.DOM provides convenience wrappers around React.createElement for DOM components.

var MyComponent = React.createClass({
  render: function() {
    return React.DOM.div({className: 'reactElement'}, 'Hello world');
  }
});

var element = React.createElement(MyComponent);
var component = ReactDOM.render(
    element,
    document.getElementById('reactContainerElement')
);

React Components

Code example

Render result (on jsfiddle)

<div id="reactContainerElement">
    <div data-reactroot class="reactElement">Hello world</div>
</div>

Haven't the access to the virtual DOM, but it can be easily converted to ReactElements

React EVENT SYSTEM

Your event handlers will be passed instances of SyntheticEvent,

a cross-browser wrapper around the browser's native event. 

All event objects conform to the W3C spec, and all events (including submit) bubble correctly per the W3C spec.

XML-LIKE SYNTAX EXTENSION TO ECMASCRIPT

var MyComponent = React.createClass({
  render: function() {
    return React.DOM.div({className: 'wrapper'}, 
        React.DOM.div({className: 'container'}, 
            React.DOM.div({className: 'reactElement'}, 
                'Hello world'
            )
        )
    );
  }
});

var element = React.createElement(MyComponent);
var component = ReactDOM.render(
    element,
    document.getElementById('reactContainerElement')
);
<div id="reactContainerElement">
    <div data-reactroot class="wrapper">
        <div class="container">
            <div class="reactElement">Hello world</div>
        </div>
    </div>
</div>

Render result (on jsfiddle)

Code example

React Component WITHOUT JSX

var Hello = React.createClass({
  render: function() {
    return (
      <div className='wrapper'>
        <div className='container'>
          <div style={{backgroundColor: 'green'}}>
            Hello world
          </div>
        </div>
      </div>
    );
  }
});

ReactDOM.render(
  <Hello />,
  document.getElementById('reactContainerElement')
);

Code example

Render result (on jsfiddle)

<div id="reactContainerElement">
    <div data-reactroot class="wrapper">
        <div class="container">
            <div class="reactElement">Hello world</div>
        </div>
    </div>
</div>

React Component WITH JSX

React.createElement(
  "div",
  { className: "navbar-header" },
  React.createElement(
    "button",
    { type: "button", className: "navbar-toggle"},
    React.createElement(
      "span",
      { className: "sr-only" },
      "Toggle navigation"
    ),
    React.createElement("span", { className: "icon-bar" }),
    React.createElement("span", { className: "icon-bar" }),
    React.createElement("span", { className: "icon-bar" })
  ),
  React.createElement(
    "a",
    { className: "navbar-brand", href: "#" },
    "Project name"
  )
);
<div className="navbar-header">
  <button type="button" className="navbar-toggle">
    <span className="sr-only">Toggle navigation</span>
    <span className="icon-bar"></span>
    <span className="icon-bar"></span>
    <span className="icon-bar"></span>
  </button>
  <a className="navbar-brand" href="#">Project name</a>
</div>

JSX GENERATE REACT ELEMENTS

Return JSX content by render() method

Convert result

support

var Photo = React.createClass({
  handleDoubleTap: function(e) { … },
  render: function() { … },
});

Classes definition syntax

class Photo extends React.Component {
  handleDoubleTap(e) { … }
  render() { … }
}

The ES5 way

The ES6+ way

var Video = React.createClass({
  getDefaultProps: function() {
    return {
      autoPlay: false,
      maxLoops: 10,
    };
  },
  getInitialState: function() {
    return {
      loopsRemaining: this.props.maxLoops,
    };
  },
  propTypes: {
    autoPlay: React.PropTypes.bool.isRequired,
    maxLoops: React.PropTypes.number.isRequired,
    posterFrameSrc: React.PropTypes.string.isRequired,
    videoSrc: React.PropTypes.string.isRequired,
  },
});

Property initializers SYNTAX*

class Video extends React.Component {
  static defaultProps = {
    autoPlay: false,
    maxLoops: 10,
  }
  static propTypes = {
    autoPlay: React.PropTypes.bool.isRequired,
    maxLoops: React.PropTypes.number.isRequired,
    posterFrameSrc: React.PropTypes.string.isRequired,
    videoSrc: React.PropTypes.string.isRequired,
  }
  state = {
    loopsRemaining: this.props.maxLoops,
  }
}

The ES5 way

The ES6+ way

* ES7+ Property Initializers

Arrow functions

var PostInfo = React.createClass({
  handleClick: function(e) {
    this.setState({
      showOptionsModal: true
    });
  },
});
class PostInfo extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(e) {
    this.setState({
      showOptionsModal: true
    });
  }
}

ES5 Way: autobinding by React.createClass

class PostInfo extends React.Component {
  handleClick = (e) => {
    this.setState({
      showOptionsModal: true
    });
  }
}

ES6+ Way: no Autobinding

ES6+ Way: arrow functions

COMPONENT DRIVEN DEVELOPMENT

concept OF

REACT COMPONENT

LIKE A LEGO BRICK

class Root extends React.Component {
  render() {
    return (
      <div>
         <Parent childName="Slim Shady" />
         <hr />
         <Parent childName="Michael Jackson" />
      </div>
    );
  }
}

class Parent extends React.Component {
  render() {
    return (
      <div>
        <div>There's my child {this.props.childName}</div> 
        <Child name={this.props.childName} />
      </div>
    );
  }
}


class Child extends React.Component {
  render() {
    return (
      <div>Hi, I'm child and my name is {this.props.name}</div>
    );
  }
}

Code example (on jsfiddle)

REACT COMPONENT PROPERTIES

REACT COMPONENT PROPERTIES

Used for communication and passed from parent to child components

ROOT

component

Component

Component

Component

Component

Component

Component

props

props

props

props

props

props

React COMPONENT PROPERTIES. VALIDATION

React.PropTypes exports a range of validators

that can be used to make sure the data you receive is valid

class MyComponent extends React.Component {

  static propTypes = {
    optionalArray: React.PropTypes.array,
    optionalBool: React.PropTypes.bool,
    optionalFunc: React.PropTypes.func,
    optionalNumber: React.PropTypes.number,

    optionalUnion: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number,
      React.PropTypes.instanceOf(Message)
    ]),

    requiredFunc: React.PropTypes.func.isRequired,

    customProp: function(props, propName, componentName) {
      if (!/matchme/.test(props[propName])) {
        return new Error('Invalid prop `' + propName + '`. Validation failed.');
      }
    }
  };

}

React COMPONENT CHILDREN propertY

class Wrapper extends React.Component {
  static propTypes = {
    children: React.PropTypes.element.isRequired
  }
  render() {
    return (
      <div className="wrapper">
        {this.props.children}
      </div>
    );
  }
}

class MyComponent extends React.Component {
  render() {
    return (
      <Wrapper>
        My component content
      </Wrapper>
    );
  }
}

With React.PropTypes.element you can specify

that only a single child can be passed to a component as children*

* Use React.Children deal with the this.props.children opaque data structure.

React COMPONENT. STATE

this.state should only contain the minimal amount of data needed to represent your UI's state.

To mutate component state use "this.setState" method*

* It does not mutate state immediately. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

React COMPONENT. STATE

class LikeButton extends React.Component {
  constructor() {
    super();
    this.state = {
      liked: false
    };
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState({
      liked: !this.state.liked
    });
  }
  render() {
    const text = this.state.liked ? 'liked' : 'haven\'t liked';
    return (
      <div onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </div>
    );
  }
}

ReactDOM.render(
  <LikeButton />,
  document.getElementById('reactContainerElement')
);

Code example (on jsfiddle)*

* Example from react official documentation

React STATELESS COMPONENT

const HelloMessage = (props) => <div>Hello, {props.name}</div>;

HelloMessage.propTypes = {
  name: React.PropTypes.string
}

HelloMessage.defaultProps = {
  name: 'John Doe'
}

ReactDOM.render(<HelloMessage name="Agent Smith"/>, mountNode);

You may also define your React compoment (class) as a plain JavaScript function.

Code example

const HelloMessage = (props) => <div>Hello {props.name}</div>;

ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);

However, you may still specify .propTypes and .defaultProps by setting them as properties on the function, just as you would set them on an ES6 class.

REACT COMPONENT LIFECYCLE

REACT COMPONENT LIFECYCLE. MOUNTING

REACT COMPONENT LIFECYCLE. UPDATING

REACT COMPONENT LIFECYCLE. UNMOUNTING

Reusability

Composition

Easy testing

React COMPONENT aproach

Communication

GIVES advantageS

NEEDS

React Components. composition

class Avatar extends React.Component {
  render() {
    return (
      <div>
        <PagePic pagename={this.props.pagename} />
        <PageLink pagename={this.props.pagename} />
      </div>
    );
  }
}

class PagePic extends React.Component {
  render() {
    return (
      <img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
    );
  }
}

class PageLink extends React.Component {
  render() {
    return (
      <a href={'https://www.facebook.com/' + this.props.pagename}>
        {this.props.pagename}
      </a>
    );
  }
}

ReactDOM.render(
  <Avatar pagename="Engineering" />,
  document.getElementById('reactContainerElement')
);

Example (on jsfiddle) of Avatar component which shows a Facebook page picture and name using the Facebook Graph API.

* Example from react official documentation

REACT COMPONENTS

COMMUNICATION

React Components. COMMUNICATION

  • Props usage
  • Refs usage

Parent TO CHILD

Techniques of communication:

React Components. COMMUNICATION

Parent TO CHILD. REFS

class Parent extends React.Component {
  constructor() {
    super();
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.refs.childRef.makeRed();
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Make it red</button>
        <Child ref='childRef' />
      </div>
    );
  }
}

class Child extends React.Component {
  constructor() {
    super();
    this.state = {
      color: 'greed'
    }
  }
  makeRed() {
    this.setState({
      color: 'red'
    })
  }
  render() {
    return (
      <div>My color is {this.state.color}</div>
    );
  }
}

Code example (on jsfiddle)

React Components. COMMUNICATION

Child to Parent

  • Callback functions

Techniques of communication:

React Components. COMMUNICATION

CHILd TO PARENT

class Parent extends React.Component {
  constructor() {
    super();
    this.state = {
      color: 'Green'
    };
  }
  mutateColor() {
    this.setState({
      color: 'Red'
    });
  }
  render() {
    return (
      <div>
        My color is {this.state.color}
        <Child handleClick={this.mutateColor.bind(this)} />
      </div>
    );
  }
}

class Child extends React.Component {
  render() {
    return (
      <div onClick={this.props.handleClick}>
        Change parent
      </div>
    );
  }
}

Code example (on jsfiddle)

React Components. COMMUNICATION

Sibling to Sibling

  • Parent Component

Techniques of communication:

React Components. COMMUNICATION

SIBLING TO SIBLING. PARENT COMPONENT

class Parent extends React.Component {
  constructor() {
    super();
    this.state = {
      propA: 'A',
      propB: 'B'
    };
  }
  mutatePropA() {
    this.setState({
      propA: 'A modified'
    });
  }
  mutatePropB() {
    this.setState({
      propB: 'B modified'
    });
  }
  render() {
    return (
      <div>
        <SiblingA
          myProp={this.state.propA}
          myFunc={this.mutatePropB.bind(this)}
          />
        <SiblingB
          myProp={this.state.propB}
          myFunc={this.mutatePropA.bind(this)}
          />
      </div>
    );
  }
}

Code example (on jsfiddle)

React Components. COMMUNICATION

Any to Any

  • Context

Techniques of communication:

Works similarly to props, but it can be used to provide data to an entire subtree.

class Root extends React.Component {
  constructor() {
    super();
    this.state = {
      locale: 'en'
    };
  }
  getChildContext() {
    return {
      setLocale: locale => this.setState({
        locale: locale
      }),
      locale: this.state.locale
    }
  }

  render() {
    return <Parent />
  }
}

Root.childContextTypes = {
  setLocale: React.PropTypes.func.isRequired,
  locale: React.PropTypes.string.isRequired
};

Code example (on jsfiddle)

class Parent extends React.Component  {
  render() {
    return <Child />;
  }
}

class Child extends React.Component {
  render() {
    const {setLocale, locale} = this.context;
    const setRussianLocale = () => setLocale('ru');

    return (
      <div>
        <div>Application state is '{locale}'!</div>
        <button onClick={setRussianLocale}>
          Set russian locale
        </button>
      </div>
    );
  }
}

Child.contextTypes = {
  setLocale: React.PropTypes.func.isRequired,
  locale: React.PropTypes.string.isRequired
}

React Components. COMMUNICATION

ANY TO ANY. CONTEXT

React Components. TESTING

  • React-addons-test-utils, official Facebook library
  • Enzyme, by airbnb

Testing libraries

import React from 'react';
import sinon from 'sinon';
import { mount } from 'enzyme';

import MyComponent from './MyComponent';
import Foo from './Foo';

describe('<Foo />', () => {
  it('allows us to set props', () => {
    const wrapper = mount(<Foo bar="baz" />);
    expect(wrapper.props().bar).to.equal('baz');
    wrapper.setProps({ bar: 'foo' });
    expect(wrapper.props().bar).to.equal('foo');
  });

  it('simulates click events', () => {
    const onButtonClick = sinon.spy();
    const wrapper = mount(
      <Foo onButtonClick={onButtonClick} />
    );
    wrapper.find('button').simulate('click');
    expect(onButtonClick).to.have.property('callCount', 1);
  });
});

Enzyme example usage

ISOMORHIC REACT

concept OF

ISOMORHIC APPLICATION

Charlie Robbins suggested the term “Isomorphic JavaScript” used to describe JavaScript code that “can execute both on the client and the server”.

And nobody knew what the hell it meant.

But now instead of just writing JavaScript the people were writing Isomorphic JavaScript.

ISOMORHIC APPLICATION

REACT Is not a framework

You will have to build application by yourself brick by brick*

*Not all of the libraries can be used as isomorhic

ISOMORHIC APPLICATION ISSUEs

Routing

Rendering

Data fetching

Persistence

Configuration

Localization

ISOMORHIC react. SERVER side RENDER

var React = require('react');
var ReactDOMServer = require('react-dom/server');

var element = React.createElement('div', null, 'Hello World!');
console.log(ReactDOMServer.renderToString(element));
ReactDOMServer.renderToString = (ReactElement) => string;
ReactDOMServer.renderToStaticMarkup = (ReactElement) => string;

API Defenitions

The react-dom/server package allows you to render your components on the server.

Usage example

NodeJS

ISOMORHIC react. Routing

There's a React Router. A complete routing library for React

import React from 'react';
import { render } from 'react-dom';
import { Router, Route, Link, browserHistory } from 'react-router';

const App = React.createClass({/*...*/});
const Users = React.createClass({/*...*/});
const User = React.createClass({/*..*/});
const NoMatch = React.createClass({/*...*/});

render((
  <Router history={browserHistory}>
    <Route path="/" component={App}>
      <Route path="users" component={Users}>
        <Route path="/user/:userId" component={User} />
      </Route>
      <Route path="*" component={NoMatch}/>
    </Route>
  </Router>
), document.getElementById('reactContainer'));

Usage example

ISOMORHIC react. LOCALIZATION

import React from 'react';
import ReactDOM from 'react-dom';
import { I18nextProvider } from 'react-i18next';

import App from './App'; // your entry page
import i18n from './i18n'; // initialized i18next instance

ReactDOM.render(
  <I18nextProvider i18n={i18n}><App /></I18nextProvider>,
  document.getElementById('app')
);

Usage example

Library react 18next

Higher-order components and components for React when using i18next.

import React from 'react';
import { translate } from 'react-i18next';

function TranslatableView(props) {
  const { t } = props;

  return (
    <div>
      <h1>{t('keyFromDefault')}</h1>
      <p>{t('anotherNamespace:key.from.another.namespace', { /* options t options */ })}</p>
    </div>
  )
}

export default translate(['defaultNamespace', 'anotherNamespace'])(TranslatableView);

USE NON-react LIBRARIES

What about other issues?

It was the only beginning

NOW You are on THE REACT way

Resources

Recomended

Used

Any questions?

React in 60 minutes. Concepts and code

By Ufocoder

React in 60 minutes. Concepts and code

  • 2,319