What is the difference between React Component and React Element? The documentation mentions both but does not go into detail, some methods require components, other elements...
相关问题
- Is there a limit to how many levels you can nest i
- How to toggle on Order in ReactJS
- How to toggle on Order in ReactJS
- void before promise syntax
- Keeping track of variable instances
React Elements
A React Element is just a plain old JavaScript
Object
without own methods. It has essentially four properties:type
, aString
representing an HTML tag or a reference referring to a React Componentkey
, aString
to uniquely identify an React Elementref
, a reference to access either the underlying DOM node or React Component Instance)props
(propertiesObject
)A React Element is not an instance of a React Component. It is just a simplified "description" of how the React Component Instance (or depending on the
type
an HTML tag) to be created should look like.A React Element that describes a React Component doesn't know to which DOM node it is eventually rendered - this association is abstracted and will be resolved while rendering.
React Elements may contain child elements and thus are capable of forming element trees, which represent the Virtual DOM tree.
React Components and React Component Instances
A custom React Component is either created by
React.createClass
or by extendingReact.Component
(ES2015). If a React Component is instantiated it expects aprops
Object
and returns an instance, which is referred to as a React Component Instance.A React Component can contain state and has access to the React Lifecycle methods. It must have at least a
render
method, which returns a React Element(-tree) when invoked. Please note that you never construct React Component Instances yourself but let React create it for you.To further elaborate on the answer, a React Element does not have any methods and nothing on the prototype. This also makes them fast.
"A ReactElement is a light, stateless, immutable, virtual representation of a DOM Element" - Glossary of React Terms
A react component
render()
function returns a DOM tree of react elements behind the scenes (This is the virtual DOM btw). There is some complex mapping and diff logic involved, but basically these React elements map to the DOM elements.You can also create a Element directly
React.createElement(arg)
where arg can be a html tag name, or a React Component class.Here is my take :
Element
is the thing that describes how to construct the VDOM. It's basically a "frozen" version of the correspondingComponent Instance
.If everything would be
functional component
then there would be no need for an extra reactElement
. Thefunctional component
hierarchy could produce the VDOM tree directly.A react
Component Instance
hierarchy (tree
) is a "factory", and that factory is parametrized by the props which are fed to the root reactComponent Instance
and by all the state "stored" anywhere in theComponent Instance
tree.So the react
Element
is basically an "abstract syntax tree" which gets compiled into the actual VDOM.So why not generate the VDOM directly by using the react
Component Instances
? This is the real question here.At the first glance I don't see why it would not be possible to do so. So most likely the answer is that it's a question of performance.
The react
Element
is one layer of abstraction between the VDOM and theComponent Instance
, why this abstraction is needed is not entirely clear to me, most likely it allows optimizations. For example theElement
tree does not get rendered completely if some lifecycle method on theComponent Instance
says that there is no need to render that subtree.Now, in this case, the logic which handles this optimization "needs" this extra layer of indirection - because the information needs to be stored somewhere that some part of the VDOM should not be compared with the new VDOM, even more, maybe the new VDOM should not be even calculated at all. So using an extra layer of indirection makes the rendering logic simpler and leads to a cleaner, more maintainable implementation - I imagine.
This concept in Haskell is called "lifting" :
For example monads in Haskell are perfect examples of such liftings.
A monad is sort of a description of a computation that can be stored as a value, like
42
. Similarly, reactElements
are elments of a description on how to compute the "new" VDOM. If somebody wants to compute it.This talk describes this concept of an "extra" indirection with some simple examples :
In other words : premature optimization is the root of all evil.
Or :Fundamental theorem of software engineering
So, in my understanding react
Elements
are an implementation detail to handle complexity gracefully and allow some optimization (performance). I don't see why one could not get rid of this extra indirection - in principle - react would still work "just as well" - but it might be super slow, implementing and maintaining the react "engine" itself would be probably a nightmare.Please correct me if I am missing here something.
Quoting an IMPORTANT part of user6445533's answer :
THIS IS THE KEY ^^^^
Element IS NOT VDOM.
A
React Element
is what you would consider to be a basic html(dom to be precise) element. It is just a way of creating element without using the much controversial jsx format.A
React Component
is what you can consider as an object. It has its methods, supportsReact lifecycles
and is generally unreusable (at least haven't found any reuse yet, welcome to examples). It necessarily needs to have a render function.A
React Class
is what you call a class. Functionality wiseReact Class
andReact Component
are same. Only syntax is the real change, asReact Component
is based onES6 syntax
. Another major change is the default binding of functions to this is no longer supported unless using arrow functions.Mixins
also are no longer supported as ofES6
.An element is a plain object describing what you want to appear on the screen in terms of the DOM nodes or other components. Elements can contain other elements in their props. Creating a React element is cheap. Once an element is created, it is never mutated. The object representation of React element would be as follows,
The above createElement returns as object as below,
And finally it renders to the DOM using ReactDOM.render as below,
Whereas a component can be declared in several different ways. It can be a class with a render() method. Alternatively, in simple cases, it can be defined as a function. In either case, it takes props as an input, and returns an element tree as the output. JSX transpiled as createElement at the end.
Consider the Component as a Class, and Element as an instance. That's it!