Skip to content

Instantly share code, notes, and snippets.

@coodoo
Forked from sebmarkbage/react-terminology.md
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coodoo/d55776d07b1aac4eab44 to your computer and use it in GitHub Desktop.
Save coodoo/d55776d07b1aac4eab44 to your computer and use it in GitHub Desktop.

React (Virtual) DOM Terminology

In React's terminology, there are five core types that are important to distinguish:

React Elements

The primary type in React is the ReactElement. It has four properties: type, props, key and ref. It has no methods and nothing on the prototype.

You can create one of these object through React.createElement.

var root = React.createElement('div');

To render a new tree into the DOM, you create ReactElements and pass them to React.render a long with a regular DOM Element (HTMLElement or SVGElement). ReactElements are not to be confused with DOM Elements. A ReactElement is a light, stateless, immutable, virtual representation of a DOM Element. It is a virtual DOM.

React.render(root, document.body);

To add properties to a DOM element, pass a properties object as the second argument and children to the third argument.

var child = React.createElement('li', null, 'Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child);
React.render(root, document.body);

If you use React JSX, then these ReactElements are created for you. So this is equivalent:

var root = <ul className="my-list">
             <li>Text Content</li>
           </ul>;
React.render(root, document.body);

Factories

A ReactElement-factory is simply a function that generates a ReactElement with a particular type property. React has a built-in helper for you to create factories. It's effectively just:

function createFactory(type){
  return React.createElement.bind(null, type);
}

It allows you to create a convenient short-hand instead of typing out React.createElement('div') all the time.

var div = React.createFactory('div');
var root = div({ className: 'my-div' });
React.render(root, document.body);

React already have built-in factories for common HTML tags:

var root = React.DOM.ul({ className: 'my-list' },
             React.DOM.li(null, 'Text Content')
           );

If you are using JSX you have no need for factories. JSX already provides a convenient short-hand for creating ReactElements.

React Nodes

A ReactNode can be either:

  • ReactElement
  • string (aka ReactText)
  • number (aka ReactText)
  • Array of ReactNodes (aka ReactFragment)

These are used as properties of other ReactElements to represent children. Effectively they create a tree of ReactElements.

React Components

You can use React using only ReactElements but to really take advantage of React, you'll want to use ReactComponents to create encapsulations with embedded state.

A ReactComponent Class is simply just a JavaScript class (or "constructor function").

var MyComponent = React.createClass({
  render: function() {
    ...
  }
});

When this constructor is invoked it is expected to return an object with at least a render method on it. This object is referred to as a ReactComponent.

var component = new MyComponent(props); // never do this

Other than for testing, you would normally never call this constructor yourself. React calls it for you.

Instead, you pass the ReactComponent Class to createElement you get a ReactElement.

var element = React.createElement(MyComponent);

OR using JSX:

var element = <MyComponent />;

When this is passed to React.render, React will call the constructor for you and create a ReactComponent, which returned.

var component = React.render(element, document.body);

If you keep calling React.render with the same type of ReactElement and the same container DOM Element it always returns the same instance. This instance is stateful.

var componentA = React.render(<MyComponent />, document.body);
var componentB = React.render(<MyComponent />, document.body);
componentA === componentB; // true

This is why you shouldn't construct your own instance. Instead, ReactElement is a virtual ReactComponent before it gets constructed. An old and new ReactElement can be compared to see if a new ReactComponent instance is created or if the existing one is reused.

The render method of a ReactComponent is expected to return another ReactElement. This allows these components to be composed. Ultimately the render resolves into ReactElement with a string tag which instantiates a DOM Element instance and inserts it into the document.

Formal Type Definitions

Entry Point

React.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;

Nodes and Elements

type ReactNode = ReactElement | ReactFragment | ReactText;

type ReactElement = ReactComponentElement | ReactDOMElement;

type ReactDOMElement = {
  type : string,
  props : {
    children : ReactNodeList,
    className : string,
    etc.
  },
  key : string | boolean | number | null,
  ref : string | null
};

type ReactComponentElement<TProps> = {
  type : ReactClass<TProps>,
  props : TProps,
  key : string | boolean | number | null,
  ref : string | null
};

type ReactFragment = Array<ReactNode | ReactEmpty>;

type ReactNodeList = ReactNode | ReactEmpty;

type ReactText = string | number;

type ReactEmpty = null | undefined | boolean;

Classes and Components

type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;

type ReactComponent<TProps> = {
  props : TProps,
  render : () => ReactElement
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment