Skip to content

Latest commit

 

History

History
709 lines (545 loc) · 35.2 KB

File metadata and controls

709 lines (545 loc) · 35.2 KB

React

22 Amazing open source React projects

React is truly only for UI. Put your business logic elsewhere in plain JavaScript objects.

The value of DI is that we can depend on abstract ideas instead of concrete implementations.

Why SPA? Imagine using Facebook where every like and every comment made you refresh the page.

Web Application has 3 parts

  1. Listen for user events
  2. Handle network events (XHR, WebSocket)
  3. Manipulate the DOM (Rendering)

Simplicity is prerequisite for reliability

KVO is built around Observables and Computed Properties.

https://github.com/reactjs/react-future/blob/master/09%20-%20Reduce%20State/01%20-%20Declarative%20Component%20Module.js

After a while, you will see the "cascading updates" problem, where a ListView will trigger a side drawer for input and once done, hide the drawer, update the ListView and update the counter, present a new dialog based on the newly added list, etc.

Context

const Text = (props, context) =>
  <p style={context}>{props.children}</p>;

Text.contextTypes = {
  fontFamily: React.PropTypes.string
};

class App extends React.Component {
  static childContextTypes = {
    fontFamily: React.PropTypes.string
  }
  getChildContext() {
    return {
      fontFamily: 'Helvetica Neue'
    };
  }
  render() {
    return <Text>Hello World</Text>;
  }
}

Real-time

Examples to Learn

File Structure Examples

Style Guides

{ this.state.show && 'This is Shown' }
{ this.state.on ? 'On' :  Off }

Move complex JSX out of render

// Notice the parentheses here.
var complexHtml = (
  <Section>
    <InnerSection />
    <InnerSection />
  </Section>
);

return (
  <div>
    { complexHtml }
  </div>
);
import React, { Component } from 'react';

class Builder extends Component {
  willTransitionTo(transition) {
    // Check authentication
  }

  componentDidMount() {
    this.databaseRef = new Firebase();
    this.databaseRef.on('dataFetched', function() {
      this.setState(...);
    });
  }

  render() {
    return ();
  }
}

Browser Support

If you need IE8 support, you need to include es5-shim yourself to make use of several Array and Date functions.

You are need to include html5shiv for IE8.

Fastclick

React.initializeTouchEvents(true); // But put where??

People

"Given the extremely tight coupling between the template and it's context (a controller/component), the concerns are the same, and splitting the DOM into a template is an arbitrary separation of technologies rather than a legit separation of concerns." - Hence in React, everything is a component. There is no template. Just define a render function.


"The React alternative is programming like you are throwing away your entire component and re-rendering it every time because it is simpler and easier to reason about. Event-based and data binding approaches frequently run into timing problems keeping track of which callback gets called first as well as make it difficult to understand how a small change in state will affect performance."

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


Mutable state and 2-way bindings made it hard to reason about.

React replaces an imperative mutating API with a declarative one that favors immutability.

Declarative -> Predictable -> Confidence -> Reliability

  • Components rather than templates
  • State is hard to manage
  • DOM insertion is painful!
  • No controller in React
  • No template in React
  • The single source of truth is all at the Component
  • All the stuffs that live on the Ember controller live in React component
  • Developed by Facebook
  • Predictable Web Framework
  • Expressive and modular
  • Just the "V"
  • Component ownership pattern (iOS-like?) - Top-level components, higher hierarchy tell children how they should render.
  • Components can be stateful
  • Encouraged 1-way data flow
  • Highly performant
  • Good practices of creating very very small components
  • Re-render everything on every change
  • Model states, not transitions
  • Declarative programming
  • Immediate mode rendering

React don't like 2-way data binding and template. It like one-way data flow and no template.

f(d) = v
f(d`) = v`
diff(v, v`) = changes
diff(v`, v) = undo # Go back in time, getting undo for free

d = data
v = virtual DOM

renderComponentToString() // Isomorphic applications

The initial HTML can be generated on the server. React handles the "view" but not with templates in the usual sense. React views are not dumb, they are "virtual DOM".

Using a difference algorithm to calculate the fewest number of steps required to render each state.

Render (and re-render) a view hierarchy to any sort of backend you want. It is DOM agnostic.

What makes UI so hard? State changing over time is evil. Model your UI as pure function.

var gulp = require('gulp');
var browserify = require('gulp-browserify]');
var concat = require('gulp-concat');

gulp.task('scripts', function() {
  gulp.src(['./src/main.js'])
      .pipe(browserify({
        transform: ['reactify']
      }))
      .pipe(concat('main.js'))
      .pipe(gulp.dest('./build'));
});

Component - ReactElement

While its true that React.createElement is an instruction in a way, all it does is return a plain object (i.e. a ReactElement). Passing that ReactElement to ReactDOM.render is what actually creates the ReactComponent. So, you can think of the ReactElement as the instruction which is passed to ReactDOM.render.

In v0.12, you no longer call it as React Component, but rather call it as ReactElement.

React is functional. Components are just like functions. They take in props and state and render HTML.

f(state, props) = UI Fragment

React.createElement('a', {href: 'http://host'}, 'Hello!')

// In JSX
<a href="http://host">Hello!</a>

// More examples
var MyComponent = React.createClass({
  render() {}
});

var element = React.createElement(MyComponent);

// MyComponent is ReactComponent and you don't normally instantiate it
var component = new MyComponent(props); // never do this

Well-written components don't even need state, so:

f(props) = UI Fragment

This introduces the concept of idempotency and immutability.

React.renderComponent();   // Deprecated
React.render();            // Use this

React.isValidComponent();  // Deprecated
React.isValidElement();    // Use this

React.PropTypes.component  // Deprecated
React.PropTypes.element    // Use this

React.PropTypes.renderable // Deprecated
React.PropTypes.node       // Use this

Components are hierarchical. Without this you won't be able to represent HTML. To access the children:

this.props.children

Components are state machines. They have properties (determined by their parent) and state (which they can change themselves, perhaps based on user actions).

Component Events

// Enable touch events for mobile devices
React.initializeTouchEvents(true);

JSX

Angular, Ember and Knockout put "JS" in your HTML. React puts "HTML" in your JS.

JSX is the key to React and it's purpose is to build composable tree/hierarchical UI.

Scale by composition - Build it small, compose it and scale it big.

Note: In v0.12, no more /** @jsx React.DOM */

<Component /> === React.createElement(Component)

const h = React.createElement;

h('ul', null, [
  h('li', null, 'Foo'),
  h('li', null, 'Bar'),
]);

const ul = React.createFactory('ul');
const li = React.createFactory('li');

ul(null, [
  li(null, 'Foo')
  li(null, 'Bar')
]);

Solved cross-site scripting?

Allow to create composite component. Component is the proper separation of concern for us. Not the 3-legged stool of HTML, CSS and JavaScript. But a single JavaScript all the way. More composable?

class HelloMessage extends React.Component {
  tick() {
    this.setState({count: this.state.count + 1});
  }
  
  render() {
    // No autowinding for tick() in v0.13.0
    return <div onClick={this.tick.bind(this)}>Hello {this.props.name}</div>;
  }
}
	
React.render(<HelloMessage name="mech" />, mountNode);

// Equivalent to this old ES3 module pattern?
function HellMessage(initialProps) {
  return {
    state: { value: initialProps.initialValue },
    render: function() {
      return <div>Hello {this.state.value}</div>;
    }
  };
}

If you use JSX, displayName is generated for you.

// See https://dev.w3.org/html5/html-author/charref

// Won't work as it is encoded
<h1>{"More info &raquo;"}</h1>

// Use Unicode instead
<h1>{"More info \u00bb"}</h1>

Conditionals and Loops in JSX

Using function is the best way to deal with conditionals. Or using variables.

// double-&&
<div className={this.state.isComplete && 'is-complete'}></div>

{isCorrect && <span className="response">{'\u2714'}</span>}

Props and States

getDefaultProps only ever called once for "all" instances. Do not do anything like Date.new inside getDefaultProps.

In Backbone, you are coding imperatively to specify when something changes, certain things should happen through it various view events setup.

In React, things are more declarative. You specify how your UI should look like at the render() and through props and states changes, the UI will change.

Declarative style require developer to think through at the start how the whole component UI look like and how they will interact.

---------     ---------
| Props |     | State |
---------     ---------
     +           +
      ----------
      | Render |
      ----------
           |
        -------   
        | DOM |
        -------
  • Props - Constant and immutable. Likely fixed from the on-set. Supplies as component attributes like <Hello name="mech" />. Try to use props as the source of truth where possible.
  • States - Can change. Mutable. You should design your component to not use state as much as possible. Try to keep as many of your components as possible stateless. Use state when you need to respond to user input, a server request or the passage of time. State should contain data that a component's event handlers may change to trigger a UI update (such as JSON request). Think of the UI as a state machine. By thinking of a UI as being in various states and rendering those states, it's easy to keep your UI consistent.

Props and states collectively represent the Model.

The final rendered DOM can have events. And once the events are triggered, the state can change which trigger another render.

If a component need to change and the cause of the change is the component's parent, then the parent can simply change the child's props and re-render.

If a component need to change due to some other component, then it need to use state.

Avoid states as much as possible. Instead push the event handling and state management up toward the top of your component hierarchy.

Note: Spread operator {...} deprecate this.transferPropsTo

A common pattern is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via props. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.

Composition (Composable)

Combine simple functions to build more complicated ones. One way to manage complexity.

Just build simple interfaces. Makes it easier to predict what will happen.

How React enable nested component? By having a clear Input (properties) and Output (render() callback function), nested components is a very common outcome.

Idempotence

Certain operations that can be applied multiple times without changing the result beyond the initial application.

Easy to predict output for a given input. Immutability gets you idempotence for free.

Virtual DOM

You would use requestIdleCallback to make DOM changes on document fragment, but you would apply the DOM patches in the next requestAnimationFrame callback, not the idle callback.

Dirty-checking model can be slow. Virtual DOM is using tree, as we all know, tree can be fast.

DOM operation is very expensive! Because modifying the DOM will also apply and calculate CSS styles, layouts, etc.

Re-render

Re-render the entire application on every change.

  • No observers
  • No magical data binding
  • No model dirty checking
  • No $apply() or $digest()

BUT: You can't just throw out the DOM and rebuild on every update? Lose form state, lost scroll position?

Director

Mithril

Mixins

Cross-cutting concern like Logger, Subscribing? Just mix in methods.

Examples

GitHub Issues

Companies using React

TDD

Books

Blog to follow

Videos

Twitter