In React's terminology, there are five core types that are important to distinguish:
- ReactElement / ReactElement Factory
- ReactNode
- ReactComponent / ReactComponent Class
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 objects through React.createElement
.
var root = React.createElement('div');
To render a new tree into the DOM, you create ReactElement
s and pass them to ReactDOM.render
along with a regular DOM Element
(HTMLElement
or SVGElement
). ReactElement
s are not to be confused with DOM Element
s. A ReactElement
is a light, stateless, immutable, virtual representation of a DOM Element
. It is a virtual DOM.
ReactDOM.render(root, document.getElementById('example'));
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); ReactDOM.render(root, document.getElementById('example'));
If you use React JSX, then these ReactElement
s are created for you. So this is equivalent:
var root = <ul className="my-list"> <li>Text Content</li> </ul>; ReactDOM.render(root, document.getElementById('example'));
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' }); ReactDOM.render(root, document.getElementById('example'));
React already has 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 ReactElement
s.
React Nodes
A ReactNode
can be either:
ReactElement
-
string
(akaReactText
) -
number
(akaReactText
) - Array of
ReactNode
s (akaReactFragment
)
These are used as properties of other ReactElement
s to represent children. Effectively they create a tree of ReactElement
s.
React Components
You can use React using only ReactElement
s but to really take advantage of React, you'll want to use ReactComponent
s 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 ReactDOM.render
, React will call the constructor for you and create a ReactComponent
, which is returned.
var component = ReactDOM.render(element, document.getElementById('example'));
If you keep calling ReactDOM.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 = ReactDOM.render(<MyComponent />, document.getElementById('example')); var componentB = ReactDOM.render(<MyComponent />, document.getElementById('example')); 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 should be created or if the existing one should be 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.
React 0.14 introduced stateless functional components as an alternative way of defining components. Instead of being a class, it is a simple function that accepts props and is expected to return a ReactElement
.
Formal Type Definitions
Entry Point
ReactDOM.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> | ReactFunctionalComponent<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 }; type ReactFunctionalComponent<TProps> = (TProps) => ReactElement;
Please login to continue.