In React's terminology, there are five core types that are important to distinguish:
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.
A ReactNode can be either:
ReactElementstring(akaReactText)number(akaReactText)- Array of
ReactNodes (akaReactFragment)
These are used as properties of other ReactElements to represent children. Effectively they create a tree of ReactElements.
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 thisOther 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; // trueThis 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.
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
};
Can someone please comment on this related SOF question : http://stackoverflow.com/questions/40480745/what-does-react-render-return-component-instance-or-component-class
In
React.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;it's not immediately clear to me ifReactComponenthere refers to a class or an instance ?My guess is that it is an instance.
If so it might be useful to rename
ReactComponenttoReactComponentInstancein that case because ifReactComponentClassis returned byReact.createClassthen what is returned beReact.render?Also, it would be good to include what is the type of
React.createElementandReact.createClassfunctions, into the formal type definitions.Or wait, is
ReactClassaReactComponentClass? IsReactClassreturned byReact.createClass?