Kim Gysen Kim Gysen - 3 months ago 19
Javascript Question

Feed native Javascript objects to React

I found interesting snippets in the following link:
https://facebook.github.io/react/blog/2015/12/18/react-components-elements-and-instances.html

The article describes how React works internally with native Javascript objects to build the tree.

Currently I'm working on a drag&drop editor for which I want to build a React component tree. Ideally I would build a tree of nested Javascript objects and convert them to a component tree at runtime.

For example, if I have an object like this (snippet from the link previousy added):

{
type: Button,
props: {
children: 'OK!',
color: 'blue'
}
}


This is what react calculates internally.
How do I feed this object (/object tree) immediately to React?

I think the snippets added are pseudo-code. The following for example will not work:

ReactDOM.render({
type: Button,
props: {
children: 'OK!',
color: 'blue'
}
}, document.getElementById('root'));

Answer

You need to add an extra property as a security measure to avoid injection of components in JSON (It is impossible to create the required symbol from JSON).

It is explained in a foot note:

All React elements require an additional $$typeof: Symbol.for('react.element') field declared on the object for security reasons. It is omitted in the examples above. This blog entry uses inline objects for elements to give you an idea of what’s happening underneath but the code won’t run as is unless you either add $$typeof to the elements, or change the code to use React.createElement() or JSX.

const Button = ({ color, children }) => <button style={{ background: color }}>{children}</button>;

ReactDOM.render({
  $$typeof: Symbol.for('react.element'),
  type: Button,
  props: {
    children: 'OK!',
    color: 'blue'
  }
}, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

Comments