JSX lets you write JavaScript function calls with HTML syntax. To generate a link in React using pure JavaScript you'd write: React.DOM.a({href: 'http://facebook.github.io/react/'}, 'Hello React!'). With JSX this becomes <a href="http://facebook.github.io/react/">Hello React!</a>. We've found this has made building React apps easier and designers tend to prefer the syntax, but everyone has their own workflow, so JSX is not required to use React.
-
JSX is very small; the "hello, world" example above uses every feature of JSX. To learn more about it, see JSX in depth. Or see the transform in action in our live JSX compiler.
+
JSX is very small; the "hello, world" example above uses every feature of JSX. To learn more about it, see JSX in depth. Or see the transform in action in our live JSX compiler.
-
JSX is similar to HTML, but not exactly the same. See JSX gotchas for some key differences.
+
JSX is similar to HTML, but not exactly the same. See JSX gotchas for some key differences.
The easiest way to get started with JSX is to use the in-browser JSXTransformer. We strongly recommend that you don't use this in production. You can precompile your code using our command-line react-tools package.
All DOM properties and attributes (including event handlers) should be camelCased to be consistent with standard JavaScript style. We intentionally break with the spec here since the spec is inconsistent.
The style attribute accepts a JavaScript object with camelCased properties rather than a CSS string. This is consistent with the DOM style JavaScript property, is more efficient, and prevents XSS security holes.
-
All event objects conform to the W3C spec, and all events (including submit) bubble correctly per the W3C spec. See Event System for more details.
-
The onChange event behaves as you would expect it to: whenever a form field is changed this event is fired rather than inconsistently on blur. We intentionally break from existing browser behavior because onChange is a misnomer for its behavior and React relies on this event to react to user input in real time. See Forms for more details.
+
All event objects conform to the W3C spec, and all events (including submit) bubble correctly per the W3C spec. See Event System for more details.
+
The onChange event behaves as you would expect it to: whenever a form field is changed this event is fired rather than inconsistently on blur. We intentionally break from existing browser behavior because onChange is a misnomer for its behavior and React relies on this event to react to user input in real time. See Forms for more details.
+
Form input attributes such as value and checked, as well as textarea. More here.
React Page is a simple React project creator to get you up-and-running quickly with React. It supports both server-side and client-side rendering, source transform and packaging JSX files using CommonJS modules, and instant reload.
React one-hour email goes step-by-step from a static HTML mock to an interactive email reader (written in just one hour!)
The XML syntax inside of JavaScript is called JSX; check out the JSX syntax to learn more about it. In order to translate it to vanilla JavaScript we use <script type="text/jsx"> and include JSXTransformer.js to actually perform the transformation in the browser.
+
The XML syntax inside of JavaScript is called JSX; check out the JSX syntax to learn more about it. In order to translate it to vanilla JavaScript we use <script type="text/jsx"> and include JSXTransformer.js to actually perform the transformation in the browser.
If you want to use React within a module system, fork our repo, npm install and run grunt. A nice set of CommonJS modules will be generated. Our jsx build tool can be integrated into most packaging systems (not just CommonJS) quite easily.
JSX doesn't follow the same whitespace elimination rules as HTML. JSX removes all whitespace between two curly braces expressions. If you want to have whitespace, simply add {' '}.
You may be thinking that it's expensive to react to changing data if there are a large number of nodes under an owner. The good news is that JavaScript is fast and render() methods tend to be quite simple, so in most applications this is extremely fast. Additionally, the bottleneck is almost always the DOM mutation and not JS execution and React will optimize this for you using batching and change detection.
-
However, sometimes you really want to have fine-grained control over your performance. In that case, simply override shouldComponentUpdate() to return false when you want React to skip processing of a subtree. See the React reference docs for more information.
+
However, sometimes you really want to have fine-grained control over your performance. In that case, simply override shouldComponentUpdate() to return false when you want React to skip processing of a subtree. See the React reference docs for more information.
React key design decision is to make the API seem like it re-renders the whole app on every update. This makes writing applications a lot easier but is also an incredible challenge to make it tractable. This article explains how with powerful heuristics we managed to turn a O(n3) problem into a O(n) one.
Generating the minimum number of operations to transform one tree into another is a complex and well-studied problem. The state of the art algorithms have a complexity in the order of O(n3) where n is the number of nodes in the tree.
+
+
This means that displaying 1000 nodes would require in the order of one billion comparisons. This is far too expensive for our use case. To put this number in perspective, CPUs nowadays execute roughly 3 billion instruction per second. So even with the most performant implementation, we wouldn't be able to compute that diff in less than a second.
+
+
Since an optimal algorithm is not tractable, we implement a non-optimal O(n) algorithm using heuristics based on two assumptions:
+
+
+
Two components of the same class will generate similar trees and two components of different classes will generate different trees.
+
It is possible to provide a unique key for elements that is stable across different renders.
+
+
+
In practice, these assumptions are ridiculously fast for almost all practical use cases.
The same logic is used for custom components. If they are not of the same type, React is not going to even try at matching what they render. It is just going to remove the first one from the DOM and insert the second one.
Having this high level knowledge is a very important aspect of why React diff algorithm is both fast and precise. It provides a good heuristic to quickly prune big parts of the tree and focus on parts likely to be similar.
+
+
It is very unlikely that a <Header> element is going generate a DOM that is going to look like what a <Content> would generate. Instead of spending time trying to match those two structures, React just re-builds the tree from scratch.
+
+
As a corollary, if there is a <Header> element at the same position in two consecutive renders, you would expect to see a very similar structure and it is worth exploring it.
We decided that the two custom components are the same. Since components are stateful, we cannot just use the new component and call it a day. React takes all the attributes from the new component and call component[Will/Did]ReceiveProps() on the previous one.
+
+
The previous component is now operational. Its render() method is called and the diff algorithm restarts with the new result and the previous result.
In order to do children reconciliation, React adopts a very naive approach. It goes over the list of children both at the same time and whenever there's a difference generates a mutation.
There are many algorithms that attempt to find the minimum sets of operations to transform a list of elements. Levenshtein distance can find the minimum using single element insertion, deletion and substitution in O(n2). Even if we were to use Levenshtein, this doesn't find when a node has moved into another position and algorithms to do that have a much worst complexity.
In order to solve this seemingly intractable issue, an optional attribute has been introduced. You can provide for each child a key that is going to be used to do the matching. If you specify a key, React is now able to find insertion, deletion, substitution and moves in O(n) using a hash table.
In practice, finding a key is not really hard. Most of the time, the element you are going to display already have a unique id. When it is not the case, you can hash some parts of the content to generate an id. Remember that the id only has to be unique among its sibling, not globally unique.
It is important to remember that the reconciliation algorithm is an implementation detail. React could re-render the whole app on every action, the end-result would be the same. We are regularly refining the heuristics in order to make common use cases faster.
+
+
In the current implementation, you can express the fact that a sub-tree has been moved between siblings, but you cannot tell that it has moved somewhere else. The algorithm will re-render that full sub-tree.
+
+
Because we rely on two heuristics, if the assumptions behind them are not met, performance will suffer.
+
+
+
The algorithm will not try to match sub-trees of different components classes. If you see yourself alternating between two components classes with very similar output, you may want to make it the same class. In practice, we haven't found this to be an issue.
+
If you don't provide stable keys (by using Math.random() for example), all the sub-trees are going to be re-rendered every single time. By giving the users the choice to chose the key, they have the ability to shoot themselves in the foot.
Components are the best way to reuse code in React, but sometimes very different components may share some common functionality. These are sometimes called cross-cutting concerns. React provides mixins to solve this problem.
-
One common use case is a component wanting to update itself on a time interval. It's easy to use setInterval(), but it's important to cancel your interval when you don't need it anymore to save memory. React provides lifecycle methods that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy setInterval() function that will automatically get cleaned up when your component is destroyed.
+
One common use case is a component wanting to update itself on a time interval. It's easy to use setInterval(), but it's important to cancel your interval when you don't need it anymore to save memory. React provides lifecycle methods that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy setInterval() function that will automatically get cleaned up when your component is destroyed.
Beside DOM differences, React offers some attributes that simply don't exist in DOM.
+
+
+
key: an optional, unique identifier. When your component shuffles around during render passes, it might be destroyed and recreated due to the diff algorithm. Assigning it a key that persists makes sure the component stays. See more here.
dangerouslySetInnerHTML: takes an object with the key __html and a DOM string as value. This is mainly for cooperating with DOM string manipulation libraries. Refer to the last example on the front page.
cx cy d fill fx fy gradientTransform gradientUnits offset points r rx ry
spreadMethod stopColor stopOpacity stroke strokeLinecap strokeWidth transform
version viewBox x1 x2 x y1 y2 y
diff --git a/docs/tooling-integration.html b/docs/tooling-integration.html
index 85495bc9dd..a7077a2819 100644
--- a/docs/tooling-integration.html
+++ b/docs/tooling-integration.html
@@ -248,6 +248,20 @@
+
Creates a component given a specification. A component implements a render method which returns one single child. That child may have an arbitrarily deep child structure. One thing that makes components different than standard prototypal classes is that you don't need to call new on them. They are convenience wrappers that construct backing instances (via new) for you.
We pass some methods in a JavaScript object to React.createClass() to create a new React component. The most important of these methods is called render which returns a tree of React components that will eventually render to HTML.
This component is different from the prior components because it will have to re-render itself. The component won't have any data until the request from the server comes back, at which point the component may need to render some new comments.
All we have done here is move the AJAX call to a separate method and call it when the component is first loaded and every 2 seconds after that. Try running this in your browser and changing the comments.json file; within 2 seconds, the changes will show!
@@ -709,8 +724,8 @@
render:function(){return(<formclassName="commentForm"onSubmit={this.handleSubmit}>
-<inputtype="text"placeholder="Your name"ref="author"/>
- <input
+<inputtype="text"placeholder="Your name"ref="author"/>
+<inputtype="text"placeholder="Say something..."ref="text"
@@ -740,12 +755,12 @@
}.bind(this)});},
- handleCommentSubmit:function(comment){
- // TODO: submit to the server and refresh the list
-},
-getInitialState:function(){
-return{data:[]};
-},
+handleCommentSubmit:function(comment){
+// TODO: submit to the server and refresh the list
+},
+getInitialState:function(){
+ return{data:[]};
+ },componentWillMount:function(){this.loadCommentsFromServer();setInterval(this.loadCommentsFromServer,this.props.pollInterval);
@@ -756,13 +771,13 @@
<h1>Comments</h1><CommentListdata={this.state.data}/><CommentForm
- onCommentSubmit={this.handleCommentSubmit}
- />
+onCommentSubmit={this.handleCommentSubmit}
+/></div>);}
-});
-
+});
+
Let's call the callback from the CommentForm when the user submits the form:
You have just built a comment box in a few simple steps. Learn more about why to use React, or dive into the API reference and start hacking! Good luck!
+
You have just built a comment box in a few simple steps. Learn more about why to use React, or dive into the API reference and start hacking! Good luck!
However, there are lots of applications that require you to read some data and flow it back into your program. For example, when developing forms, you'll often want to update some React state when you receive user input. Or perhaps you want to perform layout in JavaScript and react to changes in some DOM element size.
-
In React, you would implement this by listening to a "change" event, read from your data source (usually the DOM) and call setState() on one of your components. "Closing the data flow loop" explicitly leads to more understandable and easier-to-maintain programs. See our forms documentation for more information.
+
In React, you would implement this by listening to a "change" event, read from your data source (usually the DOM) and call setState() on one of your components. "Closing the data flow loop" explicitly leads to more understandable and easier-to-maintain programs. See our forms documentation for more information.
Two-way binding -- implicitly enforcing that some value in the DOM is always consistent with some React state -- is concise and supports a wide variety of applications. We've provided ReactLink: syntactic sugar for setting up the common data flow loop pattern described above, or "linking" some data source to React state.
@@ -374,7 +388,7 @@
}});
-
LinkedStateMixin adds a method ot your React component called linkState(). linkState() returns a ReactLink object which contains the current value of the React state and a callback to change it.
+
LinkedStateMixin adds a method to your React component called linkState(). linkState() returns a ReactLink object which contains the current value of the React state and a callback to change it.
ReactLink objects can be passed up and down the tree as props, so it's easy (and explicit) to set up two-way binding between a component deep in the hierarchy and state that lives higher in the hierarchy.
Components have three main parts of their lifecycle:
diff --git a/feed.xml b/feed.xml
index 99a5f0266a..5112c1ec52 100644
--- a/feed.xml
+++ b/feed.xml
@@ -50,7 +50,7 @@
<li>Upgraded browserify, which reduced file size by ~65KB (16KB gzipped)</li>
</ul>
- 2013-12-19T00:00:00-08:00
+ 2013-12-19T00:00:00+01:00
http://facebook.github.io/react/blog/2013/12/19/react-v0.8.0.html
http://facebook.github.io/react/blog/2013/12/19/react-v0.8.0.html
@@ -69,7 +69,7 @@
<p>You can learn more about the vulnerability discussed here: <a href="https://groups.google.com/forum/#!topic/reactjs/OIqxlB2aGfU">CVE-2013-7035</a>.</p>
- 2013-12-18T00:00:00-08:00
+ 2013-12-18T00:00:00+01:00
http://facebook.github.io/react/blog/2013/12/18/react-v0.5.2-v0.4.2.html
http://facebook.github.io/react/blog/2013/12/18/react-v0.5.2-v0.4.2.html
@@ -146,7 +146,7 @@ Is this some sort of template language? Specifically no. This might have been th
<p><img src="/react/img/blog/steve_reverse.gif" style="float: right;" />
<div style="width: 320px;"><blockquote class="twitter-tweet"><p>I think this reversed gif of Steve Urkel best describes my changing emotions towards the React Lib <a href="http://t.co/JoX0XqSXX3">http://t.co/JoX0XqSXX3</a></p>— Ryan Seddon (@ryanseddon) <a href="https://twitter.com/ryanseddon/statuses/398572848802852864">November 7, 2013</a></blockquote></div></p>
- 2013-11-18T00:00:00-08:00
+ 2013-11-18T00:00:00+01:00
http://facebook.github.io/react/blog/2013/11/18/community-roundup-11.html
http://facebook.github.io/react/blog/2013/11/18/community-roundup-11.html
@@ -262,7 +262,7 @@ Is this some sort of template language? Specifically no. This might have been th
<blockquote class="twitter-tweet"><p>This weekend <a href="https://twitter.com/search?q=%23angular&src=hash">#angular</a> died for me. Meet new king <a href="https://twitter.com/search?q=%23reactjs&src=hash">#reactjs</a></p>— Eldar Djafarov ッ (@edjafarov) <a href="https://twitter.com/edjafarov/statuses/397033796710961152">November 3, 2013</a></blockquote>
- 2013-11-06T00:00:00-08:00
+ 2013-11-06T00:00:00+01:00
http://facebook.github.io/react/blog/2013/11/06/community-roundup-10.html
http://facebook.github.io/react/blog/2013/11/06/community-roundup-10.html
@@ -408,7 +408,7 @@ Is this some sort of template language? Specifically no. This might have been th
<h2><a class="anchor" name="and-thats-it"></a>And that's it <a class="hash-link" href="#and-thats-it">#</a></h2>
<p>Hopefully this gives you an idea of how to think about building components and applications with React. While it may be a little more typing than you're used to, remember that code is read far more than it's written, and it's extremely easy to read this modular, explicit code. As you start to build large libraries of components you'll appreciate this explicitness and modularity, and with code reuse your lines of code will start to shrink :)</p>
- 2013-11-05T00:00:00-08:00
+ 2013-11-05T00:00:00+01:00
http://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html
http://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html
@@ -428,7 +428,7 @@ Is this some sort of template language? Specifically no. This might have been th
<li>Fixed bug with transition and animation event detection.</li>
</ul>
- 2013-10-29T00:00:00-07:00
+ 2013-10-29T00:00:00+01:00
http://facebook.github.io/react/blog/2013/10/29/react-v0-5-1.html
http://facebook.github.io/react/blog/2013/10/29/react-v0-5-1.html
@@ -477,7 +477,7 @@ Is this some sort of template language? Specifically no. This might have been th
<li>Improved support for maintaining line numbers when transforming.</li>
</ul>
- 2013-10-16T00:00:00-07:00
+ 2013-10-16T00:00:00+02:00
http://facebook.github.io/react/blog/2013/10/16/react-v0.5.0.html
http://facebook.github.io/react/blog/2013/10/16/react-v0.5.0.html
@@ -562,7 +562,7 @@ Is this some sort of template language? Specifically no. This might have been th
<p><a href="http://www.phpied.com/reactive-table/">Read the full article...</a></p>
</blockquote>
- 2013-10-03T00:00:00-07:00
+ 2013-10-03T00:00:00+02:00
http://facebook.github.io/react/blog/2013/10/03/community-roundup-9.html
http://facebook.github.io/react/blog/2013/10/03/community-roundup-9.html
@@ -623,7 +623,7 @@ Is this some sort of template language? Specifically no. This might have been th
<iframe width="100%" height="300" src="http://jsfiddle.net/vjeux/QL9tz/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
- 2013-09-24T00:00:00-07:00
+ 2013-09-24T00:00:00+02:00
http://facebook.github.io/react/blog/2013/09/24/community-roundup-8.html
http://facebook.github.io/react/blog/2013/09/24/community-roundup-8.html
@@ -704,7 +704,7 @@ Is this some sort of template language? Specifically no. This might have been th
<p><a href="https://github.com/facebook/react-page/">Try it out ...</a></p>
</blockquote>
- 2013-08-26T00:00:00-07:00
+ 2013-08-26T00:00:00+02:00
http://facebook.github.io/react/blog/2013/08/26/community-roundup-7.html
http://facebook.github.io/react/blog/2013/08/26/community-roundup-7.html
diff --git a/html-jsx.html b/html-jsx.html
new file mode 100644
index 0000000000..0a11397b93
--- /dev/null
+++ b/html-jsx.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+ React | HTML to JSX
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Watch this 30-minute presentation followed by a Q&A to learn more about React.
+
+
+
Get Started
diff --git a/js/html-jsx-lib.js b/js/html-jsx-lib.js
new file mode 100644
index 0000000000..9029c53ac2
--- /dev/null
+++ b/js/html-jsx-lib.js
@@ -0,0 +1,482 @@
+/**
+ * Copyright 2013 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This is a very simple HTML to JSX converter. It turns out that browsers
+ * have good HTML parsers (who would have thought?) so we utilise this by
+ * inserting the HTML into a temporary DOM node, and then do a breadth-first
+ * traversal of the resulting DOM tree.
+ */
+;(function(global) {
+ 'use strict';
+
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeType
+ var NODE_TYPE = {
+ ELEMENT: 1,
+ TEXT: 3,
+ COMMENT: 8
+ };
+ var ATTRIBUTE_MAPPING = {
+ 'for': 'htmlFor',
+ 'class': 'className'
+ };
+
+ /**
+ * Repeats a string a certain number of times.
+ * Also: the future is bright and consists of native string repetition:
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
+ *
+ * @param {string} string String to repeat
+ * @param {number} times Number of times to repeat string. Integer.
+ * @see http://jsperf.com/string-repeater/2
+ */
+ function repeatString(string, times) {
+ if (times === 1) {
+ return string;
+ }
+ if (times < 0) { throw new Error(); }
+ var repeated = '';
+ while (times) {
+ if (times & 1) {
+ repeated += string;
+ }
+ if (times >>= 1) {
+ string += string;
+ }
+ }
+ return repeated;
+ }
+
+ /**
+ * Determine if the string ends with the specified substring.
+ *
+ * @param {string} haystack String to search in
+ * @param {string} needle String to search for
+ * @return {boolean}
+ */
+ function endsWith(haystack, needle) {
+ return haystack.slice(-needle.length) === needle;
+ }
+
+ /**
+ * Trim the specified substring off the string. If the string does not end
+ * with the specified substring, this is a no-op.
+ *
+ * @param {string} haystack String to search in
+ * @param {string} needle String to search for
+ * @return {string}
+ */
+ function trimEnd(haystack, needle) {
+ return endsWith(haystack, needle)
+ ? haystack.slice(0, -needle.length)
+ : haystack;
+ }
+
+ /**
+ * Convert a hyphenated string to camelCase.
+ */
+ function hyphenToCamelCase(string) {
+ return string.replace(/-(.)/g, function(match, chr) {
+ return chr.toUpperCase();
+ });
+ }
+
+ /**
+ * Determines if the specified string consists entirely of whitespace.
+ */
+ function isEmpty(string) {
+ return !/[^\s]/.test(string);
+ }
+
+ /**
+ * Determines if the specified string consists entirely of numeric characters.
+ */
+ function isNumeric(input) {
+ return input !== undefined
+ && input !== null
+ && (typeof input === 'number' || parseInt(input, 10) == input);
+ }
+
+ var HTMLtoJSX = function(config) {
+ this.config = config || {};
+
+ if (this.config.createClass === undefined) {
+ this.config.createClass = true;
+ }
+ if (!this.config.indent) {
+ this.config.indent = ' ';
+ }
+ if (!this.config.outputClassName) {
+ this.config.outputClassName = 'NewComponent';
+ }
+ };
+ HTMLtoJSX.prototype = {
+ /**
+ * Reset the internal state of the converter
+ */
+ reset: function() {
+ this.output = '';
+ this.level = 0;
+ },
+ /**
+ * Main entry point to the converter. Given the specified HTML, returns a
+ * JSX object representing it.
+ * @param {string} html HTML to convert
+ * @return {string} JSX
+ */
+ convert: function(html) {
+ this.reset();
+
+ // It turns out browsers have good HTML parsers (imagine that).
+ // Let's take advantage of it.
+ var containerEl = document.createElement('div');
+ containerEl.innerHTML = '\n' + this._cleanInput(html) + '\n';
+
+ if (this.config.createClass) {
+ if (this.config.outputClassName) {
+ this.output = 'var ' + this.config.outputClassName + ' = React.createClass({\n';
+ } else {
+ this.output = 'React.createClass({\n';
+ }
+ this.output += this.config.indent + 'render: function() {' + "\n";
+ this.output += this.config.indent + this.config.indent + 'return (\n';
+ }
+
+ if (this._onlyOneTopLevel(containerEl)) {
+ // Only one top-level element, the component can return it directly
+ // No need to actually visit the container element
+ this._traverse(containerEl);
+ } else {
+ // More than one top-level element, need to wrap the whole thing in a
+ // container.
+ this.output += this.config.indent + this.config.indent + this.config.indent;
+ this.level++;
+ this._visit(containerEl);
+ }
+ this.output = this.output.trim() + '\n';
+ if (this.config.createClass) {
+ this.output += this.config.indent + this.config.indent + ');\n';
+ this.output += this.config.indent + '}\n';
+ this.output += '});';
+ }
+ return this.output;
+ },
+
+ /**
+ * Cleans up the specified HTML so it's in a format acceptable for
+ * converting.
+ *
+ * @param {string} html HTML to clean
+ * @return {string} Cleaned HTML
+ */
+ _cleanInput: function(html) {
+ // Remove unnecessary whitespace
+ html = html.trim();
+ // Ugly method to strip script tags. They can wreak havoc on the DOM nodes
+ // so let's not even put them in the DOM.
+ html = html.replace(/