mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
1164 lines
109 KiB
HTML
1164 lines
109 KiB
HTML
<!DOCTYPE html>
|
|
<!--[if IE]><![endif]-->
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
<title>Tutorial | React</title>
|
|
<meta name="viewport" content="width=device-width">
|
|
<meta property="og:title" content="Tutorial | React">
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:url" content="https://facebook.github.io/react/docs/tutorial.html">
|
|
<meta property="og:image" content="https://facebook.github.io/react/img/logo_og.png">
|
|
<meta property="og:description" content="A JavaScript library for building user interfaces">
|
|
<meta property="fb:app_id" content="623268441017527">
|
|
|
|
<link rel="shortcut icon" href="/react/favicon.ico">
|
|
<link rel="alternate" type="application/rss+xml" title="React" href="https://facebook.github.io/react/feed.xml">
|
|
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css" />
|
|
<link rel="stylesheet" href="/react/css/syntax.css">
|
|
<link rel="stylesheet" href="/react/css/codemirror.css">
|
|
<link rel="stylesheet" href="/react/css/react.css">
|
|
|
|
<script src="//use.typekit.net/vqa1hcx.js"></script>
|
|
<script>try{Typekit.load();}catch(e){}</script>
|
|
|
|
<!--[if lte IE 8]>
|
|
<script src="/react/js/html5shiv.min.js"></script>
|
|
<script src="/react/js/es5-shim.min.js"></script>
|
|
<script src="/react/js/es5-sham.min.js"></script>
|
|
<![endif]-->
|
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
|
|
<script src="/react/js/codemirror.js"></script>
|
|
<script src="/react/js/javascript.js"></script>
|
|
<script src="/react/js/xml.js"></script>
|
|
<script src="/react/js/jsx.js"></script>
|
|
<script src="/react/js/react.js"></script>
|
|
<script src="/react/js/react-dom.js"></script>
|
|
<script src="/react/js/babel-browser.min.js"></script>
|
|
<script src="/react/js/live_editor.js"></script>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="container">
|
|
|
|
<div class="nav-main">
|
|
<div class="wrap">
|
|
<a class="nav-home" href="/react/index.html">
|
|
<img class="nav-logo" src="/react/img/logo.svg" width="36" height="36">
|
|
React
|
|
</a>
|
|
<ul class="nav-site nav-site-internal">
|
|
<li><a href="/react/docs/getting-started.html" class="active">Docs</a></li>
|
|
<li><a href="/react/support.html">Support</a></li>
|
|
<li><a href="/react/downloads.html">Download</a></li>
|
|
<li><a href="/react/blog/">Blog</a></li>
|
|
<li>
|
|
<input id="algolia-doc-search" type="text" placeholder="Search docs..." />
|
|
</li>
|
|
</ul>
|
|
|
|
<ul class="nav-site nav-site-external">
|
|
<li><a href="https://github.com/facebook/react">GitHub</a></li>
|
|
<li><a href="https://facebook.github.io/react-native/">React Native</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<section class="content wrap documentationContent">
|
|
<div class="nav-docs">
|
|
<!-- Docs Nav -->
|
|
|
|
<div class="nav-docs-section">
|
|
<h3>Quick Start</h3>
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/docs/getting-started.html">Getting Started</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/tutorial.html" class="active">Tutorial</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/thinking-in-react.html">Thinking in React</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-docs-section">
|
|
<h3>Community Resources</h3>
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/docs/conferences.html">Conferences</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/videos.html">Videos</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://github.com/facebook/react/wiki/Complementary-Tools" class="external">Complementary Tools</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://github.com/facebook/react/wiki/Examples" class="external">Examples</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-docs-section">
|
|
<h3>Guides</h3>
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/docs/why-react.html">Why React?</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/displaying-data.html">Displaying Data</a>
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/docs/jsx-in-depth.html">JSX in Depth</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/jsx-spread.html">JSX Spread Attributes</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/jsx-gotchas.html">JSX Gotchas</a>
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/interactivity-and-dynamic-uis.html">Interactivity and Dynamic UIs</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/multiple-components.html">Multiple Components</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/reusable-components.html">Reusable Components</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/transferring-props.html">Transferring Props</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/forms.html">Forms</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/working-with-the-browser.html">Working With the Browser</a>
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/docs/more-about-refs.html">Refs to Components</a>
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/tooling-integration.html">Tooling Integration</a>
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/docs/language-tooling.html">Language Tooling</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/package-management.html">Package Management</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/environments.html">Server-side Environments</a>
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/addons.html">Add-Ons</a>
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/docs/animation.html">Animation</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/two-way-binding-helpers.html">Two-Way Binding Helpers</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/test-utils.html">Test Utilities</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/clone-with-props.html">Cloning Elements</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/create-fragment.html">Keyed Fragments</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/update.html">Immutability Helpers</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/pure-render-mixin.html">PureRenderMixin</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/perf.html">Performance Tools</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/shallow-compare.html">Shallow Compare</a>
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/advanced-performance.html">Advanced Performance</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/context.html">Context</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-docs-section">
|
|
<h3>Reference</h3>
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/docs/top-level-api.html">Top-Level API</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/component-api.html">Component API</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/component-specs.html">Component Specs and Lifecycle</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/tags-and-attributes.html">Supported Tags and Attributes</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/events.html">Event System</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/dom-differences.html">DOM Differences</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/special-non-dom-attributes.html">Special Non-DOM Attributes</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/reconciliation.html">Reconciliation</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/webcomponents.html">Web Components</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/docs/glossary.html">React (Virtual) DOM Terminology</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
<!-- Tips Nav -->
|
|
|
|
<div class="nav-docs-section">
|
|
<h3>Tips</h3>
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/tips/introduction.html">Introduction</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/inline-styles.html">Inline Styles</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/if-else-in-JSX.html">If-Else in JSX</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/self-closing-tag.html">Self-Closing Tag</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/maximum-number-of-jsx-root-nodes.html">Maximum Number of JSX Root Nodes</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/style-props-value-px.html">Shorthand for Specifying Pixel Values in style props</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/children-props-type.html">Type of the Children props</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/controlled-input-null-value.html">Value of null for Controlled Input</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/componentWillReceiveProps-not-triggered-after-mounting.html">componentWillReceiveProps Not Triggered After Mounting</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/props-in-getInitialState-as-anti-pattern.html">Props in getInitialState Is an Anti-Pattern</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/dom-event-listeners.html">DOM Event Listeners in a Component</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/initial-ajax.html">Load Initial Data via AJAX</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/false-in-jsx.html">False in JSX</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/communicate-between-components.html">Communicate Between Components</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/expose-component-functions.html">Expose Component Functions</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/children-undefined.html">this.props.children undefined</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/use-react-with-other-libraries.html">Use React with Other Libraries</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/tips/dangerously-set-inner-html.html">Dangerously Set innerHTML</a>
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
<!-- Contributing Nav -->
|
|
|
|
<div class="nav-docs-section">
|
|
<h3>Contributing</h3>
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="/react/contributing/how-to-contribute.html">How to Contribute</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/contributing/codebase-overview.html">Codebase Overview</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/react/contributing/design-principles.html">Design Principles</a>
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div class="inner-content">
|
|
<a class="edit-page-link" href="https://github.com/facebook/react/tree/master/docs/docs/tutorial.md" target="_blank">Edit on GitHub</a>
|
|
<h1>
|
|
Tutorial
|
|
</h1>
|
|
<div class="subHeader"></div>
|
|
|
|
<p>We'll be building a simple but realistic comments box that you can drop into a blog, a basic version of the realtime comments offered by Disqus, LiveFyre or Facebook comments.</p>
|
|
|
|
<p>We'll provide:</p>
|
|
|
|
<ul>
|
|
<li>A view of all of the comments</li>
|
|
<li>A form to submit a comment</li>
|
|
<li>Hooks for you to provide a custom backend</li>
|
|
</ul>
|
|
|
|
<p>It'll also have a few neat features:</p>
|
|
|
|
<ul>
|
|
<li><strong>Optimistic commenting:</strong> comments appear in the list before they're saved on the server so it feels fast.</li>
|
|
<li><strong>Live updates:</strong> other users' comments are popped into the comment view in real time.</li>
|
|
<li><strong>Markdown formatting:</strong> users can use Markdown to format their text.</li>
|
|
</ul>
|
|
<h3><a class="anchor" name="want-to-skip-all-this-and-just-see-the-source"></a>Want to skip all this and just see the source? <a class="hash-link" href="#want-to-skip-all-this-and-just-see-the-source">#</a></h3>
|
|
<p><a href="https://github.com/reactjs/react-tutorial">It's all on GitHub.</a></p>
|
|
<h3><a class="anchor" name="running-a-server"></a>Running a server <a class="hash-link" href="#running-a-server">#</a></h3>
|
|
<p>In order to start this tutorial, we're going to require a running server. This will serve purely as an API endpoint which we'll use for getting and saving data. In order to make this as easy as possible, we've created a simple server in a number of scripting languages that does exactly what we need it to do. <strong>You can <a href="https://github.com/reactjs/react-tutorial/">view the source</a> or <a href="https://github.com/reactjs/react-tutorial/archive/master.zip">download a zip file</a> containing everything needed to get started.</strong></p>
|
|
|
|
<p>For sake of simplicity, the server we will run uses a <code>JSON</code> file as a database. You would not run this in production but it makes it easy to simulate what you might do when consuming an API. Once you <a href="https://github.com/reactjs/react-tutorial/#to-use">start the server</a>, it will support our API endpoint and it will also serve the static pages we need.</p>
|
|
<h3><a class="anchor" name="getting-started"></a>Getting started <a class="hash-link" href="#getting-started">#</a></h3>
|
|
<p>For this tutorial, we're going to make it as easy as possible. Included in the server package discussed above is an HTML file which we'll work in. Open up <code>public/index.html</code> in your favorite editor. It should look something like this:</p>
|
|
<div class="highlight"><pre><code class="language-html" data-lang="html"><span class="c"><!-- index.html --></span>
|
|
<span class="cp"><!DOCTYPE html></span>
|
|
<span class="nt"><html></span>
|
|
<span class="nt"><head></span>
|
|
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span> <span class="nt">/></span>
|
|
<span class="nt"><title></span>React Tutorial<span class="nt"></title></span>
|
|
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://unpkg.com/react@15.3.2/dist/react.js"</span><span class="nt">></script></span>
|
|
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"</span><span class="nt">></script></span>
|
|
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://unpkg.com/babel-core@5.8.38/browser.min.js"</span><span class="nt">></script></span>
|
|
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"</span><span class="nt">></script></span>
|
|
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"</span><span class="nt">></script></span>
|
|
<span class="nt"></head></span>
|
|
<span class="nt"><body></span>
|
|
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"content"</span><span class="nt">></div></span>
|
|
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/babel"</span> <span class="na">src=</span><span class="s">"scripts/example.js"</span><span class="nt">></script></span>
|
|
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/babel"</span><span class="nt">></span>
|
|
<span class="c1">// To get started with this tutorial running your own code, simply remove</span>
|
|
<span class="c1">// the script tag loading scripts/example.js and start writing code here.</span>
|
|
<span class="nt"></script></span>
|
|
<span class="nt"></body></span>
|
|
<span class="nt"></html></span>
|
|
</code></pre></div>
|
|
<p>For the remainder of this tutorial, we'll be writing our JavaScript code in this script tag. We don't have any advanced live-reloading so you'll need to refresh your browser to see updates after saving. Follow your progress by opening <code>http://localhost:3000</code> in your browser (after starting the server). When you load this for the first time without any changes, you'll see the finished product of what we're going to build. When you're ready to start working, just delete the preceding <code><script></code> tag and then you can continue.</p>
|
|
|
|
<blockquote>
|
|
<p>Note:</p>
|
|
|
|
<p>We included jQuery here because we want to simplify the code of our future AJAX calls, but it's <strong>NOT</strong> mandatory for React to work.</p>
|
|
</blockquote>
|
|
<h3><a class="anchor" name="your-first-component"></a>Your first component <a class="hash-link" href="#your-first-component">#</a></h3>
|
|
<p>React is all about modular, composable components. For our comment box example, we'll have the following component structure:</p>
|
|
<div class="highlight"><pre><code class="language-text" data-lang="text">- CommentBox
|
|
- CommentList
|
|
- Comment
|
|
- CommentForm
|
|
</code></pre></div>
|
|
<p>Let's build the <code>CommentBox</code> component, which is just a simple <code><div></code>:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial1.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="nx">Hello</span><span class="p">,</span> <span class="nx">world</span><span class="o">!</span> <span class="nx">I</span> <span class="nx">am</span> <span class="nx">a</span> <span class="nx">CommentBox</span><span class="p">.</span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">CommentBox</span> <span class="o">/></span><span class="p">,</span>
|
|
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'content'</span><span class="p">)</span>
|
|
<span class="p">);</span>
|
|
</code></pre></div>
|
|
<p>Note that native HTML element names start with a lowercase letter, while custom React class names begin with an uppercase letter.</p>
|
|
<h4><a class="anchor" name="jsx-syntax"></a>JSX Syntax <a class="hash-link" href="#jsx-syntax">#</a></h4>
|
|
<p>The first thing you'll notice is the XML-ish syntax in your JavaScript. We have a simple precompiler that translates the syntactic sugar to this plain JavaScript:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial1-raw.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span><span class="nx">displayName</span><span class="o">:</span> <span class="s1">'CommentBox'</span><span class="p">,</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="nx">React</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'div'</span><span class="p">,</span> <span class="p">{</span><span class="nx">className</span><span class="o">:</span> <span class="s2">"commentBox"</span><span class="p">},</span>
|
|
<span class="s2">"Hello, world! I am a CommentBox."</span>
|
|
<span class="p">)</span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span>
|
|
<span class="nx">React</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="nx">CommentBox</span><span class="p">,</span> <span class="kc">null</span><span class="p">),</span>
|
|
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'content'</span><span class="p">)</span>
|
|
<span class="p">);</span>
|
|
</code></pre></div>
|
|
<p>Its use is optional but we've found JSX syntax easier to use than plain JavaScript. Read more on the <a href="/react/docs/jsx-in-depth.html">JSX Syntax article</a>.</p>
|
|
<h4><a class="anchor" name="whats-going-on"></a>What's going on <a class="hash-link" href="#whats-going-on">#</a></h4>
|
|
<p>We pass some methods in a JavaScript object to <code>React.createClass()</code> to create a new React component. The most important of these methods is called <code>render</code> which returns a tree of React components that will eventually render to HTML.</p>
|
|
|
|
<p>The <code><div></code> tags are not actual DOM nodes; they are instantiations of React <code>div</code> components. You can think of these as markers or pieces of data that React knows how to handle. React is <strong>safe</strong>. We are not generating HTML strings so XSS protection is the default.</p>
|
|
|
|
<p>You do not have to return basic HTML. You can return a tree of components that you (or someone else) built. This is what makes React <strong>composable</strong>: a key tenet of maintainable frontends.</p>
|
|
|
|
<p><code>ReactDOM.render()</code> instantiates the root component, starts the framework, and injects the markup into a raw DOM element, provided as the second argument.</p>
|
|
|
|
<p>The <code>ReactDOM</code> module exposes DOM-specific methods, while <code>React</code> has the core tools shared by React on different platforms (e.g., <a href="http://facebook.github.io/react-native/">React Native</a>).</p>
|
|
|
|
<p>It is important that <code>ReactDOM.render</code> remain at the bottom of the script for this tutorial. <code>ReactDOM.render</code> should only be called after the composite components have been defined.</p>
|
|
<h2><a class="anchor" name="composing-components"></a>Composing components <a class="hash-link" href="#composing-components">#</a></h2>
|
|
<p>Let's build skeletons for <code>CommentList</code> and <code>CommentForm</code> which will, again, be simple <code><div></code>s. Add these two components to your file, keeping the existing <code>CommentBox</code> declaration and <code>ReactDOM.render</code> call:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial2.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentList</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentList"</span><span class="o">></span>
|
|
<span class="nx">Hello</span><span class="p">,</span> <span class="nx">world</span><span class="o">!</span> <span class="nx">I</span> <span class="nx">am</span> <span class="nx">a</span> <span class="nx">CommentList</span><span class="p">.</span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">CommentForm</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentForm"</span><span class="o">></span>
|
|
<span class="nx">Hello</span><span class="p">,</span> <span class="nx">world</span><span class="o">!</span> <span class="nx">I</span> <span class="nx">am</span> <span class="nx">a</span> <span class="nx">CommentForm</span><span class="p">.</span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>Next, update the <code>CommentBox</code> component to use these new components:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial3.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Comments</span><span class="o"><</span><span class="err">/h1></span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="nx">CommentList</span> <span class="o">/></span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="nx">CommentForm</span> <span class="o">/></span>
|
|
</span> <span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>Notice how we're mixing HTML tags and components we've built. HTML components are regular React components, just like the ones you define, with one difference. The JSX compiler will automatically rewrite HTML tags to <code>React.createElement(tagName)</code> expressions and leave everything else alone. This is to prevent the pollution of the global namespace.</p>
|
|
<h3><a class="anchor" name="using-props"></a>Using props <a class="hash-link" href="#using-props">#</a></h3>
|
|
<p>Let's create the <code>Comment</code> component, which will depend on data passed in from its parent, <code>CommentList</code>. Data passed in from a parent component is available as a 'property' on the child component. These 'properties' are accessed through <code>this.props</code>. Using props, we will be able to read the data passed to the <code>Comment</code> from the <code>CommentList</code>, and render some markup:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial4.js</span>
|
|
<span class="kd">var</span> <span class="nx">Comment</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"comment"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h2</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentAuthor"</span><span class="o">></span>
|
|
<span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">author</span><span class="p">}</span>
|
|
<span class="o"><</span><span class="err">/h2></span>
|
|
<span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">children</span><span class="p">}</span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>By surrounding a JavaScript expression in braces inside JSX (as either an attribute or child), you can drop text or React components into the tree. We access named attributes passed to the component as keys on <code>this.props</code> and any nested elements as <code>this.props.children</code>.</p>
|
|
<h3><a class="anchor" name="component-properties"></a>Component Properties <a class="hash-link" href="#component-properties">#</a></h3>
|
|
<p>Now that we have defined the <code>Comment</code> component, we will want to pass it the author name and comment text. This allows us to reuse the same code for each unique comment. Now let's add some comments within our <code>CommentList</code>:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial5.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentList</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentList"</span><span class="o">></span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">Comment</span> <span class="nx">author</span><span class="o">=</span><span class="s2">"Pete Hunt"</span><span class="o">></span><span class="nx">This</span> <span class="nx">is</span> <span class="nx">one</span> <span class="nx">comment</span><span class="o"><</span><span class="err">/Comment></span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="nx">Comment</span> <span class="nx">author</span><span class="o">=</span><span class="s2">"Jordan Walke"</span><span class="o">></span><span class="nx">This</span> <span class="nx">is</span> <span class="o">*</span><span class="nx">another</span><span class="o">*</span> <span class="nx">comment</span><span class="o"><</span><span class="err">/Comment></span>
|
|
</span> <span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>Note that we have passed some data from the parent <code>CommentList</code> component to the child <code>Comment</code> components. For example, we passed <em>Pete Hunt</em> (via the <code>author</code> attribute) and <em>This is one comment</em> (via an XML-like child node) to the first <code>Comment</code>. As noted above, the <code>Comment</code> component will access these 'properties' through <code>this.props.author</code>, and <code>this.props.children</code>.</p>
|
|
<h3><a class="anchor" name="adding-markdown"></a>Adding Markdown <a class="hash-link" href="#adding-markdown">#</a></h3>
|
|
<p>Markdown is a simple way to format your text inline. For example, surrounding text with asterisks will make it emphasized.</p>
|
|
|
|
<p>In this tutorial we use a third-party library <strong>remarkable</strong> which takes Markdown text and converts it to raw HTML. We already included this library with the original markup for the page, so we can just start using it. Let's convert the comment text to Markdown and output it:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial6.js</span>
|
|
<span class="kd">var</span> <span class="nx">Comment</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="hll"> <span class="kd">var</span> <span class="nx">md</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Remarkable</span><span class="p">();</span>
|
|
</span> <span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"comment"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h2</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentAuthor"</span><span class="o">></span>
|
|
<span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">author</span><span class="p">}</span>
|
|
<span class="o"><</span><span class="err">/h2></span>
|
|
<span class="hll"> <span class="p">{</span><span class="nx">md</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">children</span><span class="p">.</span><span class="nx">toString</span><span class="p">())}</span>
|
|
</span> <span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>All we're doing here is calling the remarkable library. We need to convert <code>this.props.children</code> from React's wrapped text to a raw string that remarkable will understand so we explicitly call <code>toString()</code>.</p>
|
|
|
|
<p>But there's a problem! Our rendered comments look like this in the browser: "<code><p></code>This is <code><em></code>another<code></em></code> comment<code></p></code>". We want those tags to actually render as HTML.</p>
|
|
|
|
<p>That's React protecting you from an <a href="https://en.wikipedia.org/wiki/Cross-site_scripting">XSS attack</a>. There's a way to get around it but the framework warns you not to use it:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial7.js</span>
|
|
<span class="kd">var</span> <span class="nx">Comment</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="hll"> <span class="nx">rawMarkup</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="kd">var</span> <span class="nx">md</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Remarkable</span><span class="p">();</span>
|
|
</span><span class="hll"> <span class="kd">var</span> <span class="nx">rawMarkup</span> <span class="o">=</span> <span class="nx">md</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">children</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
|
</span><span class="hll"> <span class="k">return</span> <span class="p">{</span> <span class="nx">__html</span><span class="o">:</span> <span class="nx">rawMarkup</span> <span class="p">};</span>
|
|
</span><span class="hll"> <span class="p">},</span>
|
|
</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"comment"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h2</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentAuthor"</span><span class="o">></span>
|
|
<span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">author</span><span class="p">}</span>
|
|
<span class="o"><</span><span class="err">/h2></span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">span</span> <span class="nx">dangerouslySetInnerHTML</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">rawMarkup</span><span class="p">()}</span> <span class="o">/></span>
|
|
</span> <span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>This is a special API that intentionally makes it difficult to insert raw HTML, but for remarkable we'll take advantage of this backdoor.</p>
|
|
|
|
<p><strong>Remember:</strong> by using this feature you're relying on remarkable to be secure. In this case, remarkable automatically strips HTML markup and insecure links from the output.</p>
|
|
<h3><a class="anchor" name="hook-up-the-data-model"></a>Hook up the data model <a class="hash-link" href="#hook-up-the-data-model">#</a></h3>
|
|
<p>So far we've been inserting the comments directly in the source code. Instead, let's render a blob of JSON data into the comment list. Eventually this will come from the server, but for now, write it in your source:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial8.js</span>
|
|
<span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span><span class="nx">id</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">author</span><span class="o">:</span> <span class="s2">"Pete Hunt"</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="s2">"This is one comment"</span><span class="p">},</span>
|
|
<span class="p">{</span><span class="nx">id</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">author</span><span class="o">:</span> <span class="s2">"Jordan Walke"</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="s2">"This is *another* comment"</span><span class="p">}</span>
|
|
<span class="p">];</span>
|
|
</code></pre></div>
|
|
<p>We need to get this data into <code>CommentList</code> in a modular way. Modify <code>CommentBox</code> and the <code>ReactDOM.render()</code> call to pass this data into the <code>CommentList</code> via props:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial9.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Comments</span><span class="o"><</span><span class="err">/h1></span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">CommentList</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">data</span><span class="p">}</span> <span class="o">/></span>
|
|
</span> <span class="o"><</span><span class="nx">CommentForm</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
|
|
<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">CommentBox</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="nx">data</span><span class="p">}</span> <span class="o">/></span><span class="p">,</span>
|
|
</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'content'</span><span class="p">)</span>
|
|
<span class="p">);</span>
|
|
</code></pre></div>
|
|
<p>Now that the data is available in the <code>CommentList</code>, let's render the comments dynamically:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial10.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentList</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="hll"> <span class="kd">var</span> <span class="nx">commentNodes</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">comment</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="k">return</span> <span class="p">(</span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="nx">Comment</span> <span class="nx">author</span><span class="o">=</span><span class="p">{</span><span class="nx">comment</span><span class="p">.</span><span class="nx">author</span><span class="p">}</span> <span class="nx">key</span><span class="o">=</span><span class="p">{</span><span class="nx">comment</span><span class="p">.</span><span class="nx">id</span><span class="p">}</span><span class="o">></span>
|
|
</span><span class="hll"> <span class="p">{</span><span class="nx">comment</span><span class="p">.</span><span class="nx">text</span><span class="p">}</span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="err">/Comment></span>
|
|
</span><span class="hll"> <span class="p">);</span>
|
|
</span><span class="hll"> <span class="p">});</span>
|
|
</span> <span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentList"</span><span class="o">></span>
|
|
<span class="hll"> <span class="p">{</span><span class="nx">commentNodes</span><span class="p">}</span>
|
|
</span> <span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>That's it!</p>
|
|
<h3><a class="anchor" name="fetching-from-the-server"></a>Fetching from the server <a class="hash-link" href="#fetching-from-the-server">#</a></h3>
|
|
<p>Let's replace the hard-coded data with some dynamic data from the server. We will remove the data prop and replace it with a URL to fetch:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial11.js</span>
|
|
<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">CommentBox</span> <span class="nx">url</span><span class="o">=</span><span class="s2">"/api/comments"</span> <span class="o">/></span><span class="p">,</span>
|
|
</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'content'</span><span class="p">)</span>
|
|
<span class="p">);</span>
|
|
</code></pre></div>
|
|
<p>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.</p>
|
|
|
|
<p>Note: the code will not be working at this step.</p>
|
|
<h3><a class="anchor" name="reactive-state"></a>Reactive state <a class="hash-link" href="#reactive-state">#</a></h3>
|
|
<p>So far, based on its props, each component has rendered itself once. <code>props</code> are immutable: they are passed from the parent and are "owned" by the parent. To implement interactions, we introduce mutable <strong>state</strong> to the component. <code>this.state</code> is private to the component and can be changed by calling <code>this.setState()</code>. When the state updates, the component re-renders itself.</p>
|
|
|
|
<p><code>render()</code> methods are written declaratively as functions of <code>this.props</code> and <code>this.state</code>. The framework guarantees the UI is always consistent with the inputs.</p>
|
|
|
|
<p>When the server fetches data, we will be changing the comment data we have. Let's add an array of comment data to the <code>CommentBox</code> component as its state:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial12.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="hll"> <span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="k">return</span> <span class="p">{</span><span class="nx">data</span><span class="o">:</span> <span class="p">[]};</span>
|
|
</span><span class="hll"> <span class="p">},</span>
|
|
</span> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Comments</span><span class="o"><</span><span class="err">/h1></span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">CommentList</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">data</span><span class="p">}</span> <span class="o">/></span>
|
|
</span> <span class="o"><</span><span class="nx">CommentForm</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p><code>getInitialState()</code> executes exactly once during the lifecycle of the component and sets up the initial state of the component.</p>
|
|
<h4><a class="anchor" name="updating-state"></a>Updating state <a class="hash-link" href="#updating-state">#</a></h4>
|
|
<p>When the component is first created, we want to GET some JSON from the server and update the state to reflect the latest data. We're going to use jQuery to make an asynchronous request to the server we started earlier to fetch the data we need. The data is already included in the server you started (based on the <code>comments.json</code> file), so once it's fetched, <code>this.state.data</code> will look something like this:</p>
|
|
<div class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">[</span>
|
|
<span class="p">{</span><span class="nt">"id"</span><span class="p">:</span> <span class="s2">"1"</span><span class="p">,</span> <span class="nt">"author"</span><span class="p">:</span> <span class="s2">"Pete Hunt"</span><span class="p">,</span> <span class="nt">"text"</span><span class="p">:</span> <span class="s2">"This is one comment"</span><span class="p">},</span>
|
|
<span class="p">{</span><span class="nt">"id"</span><span class="p">:</span> <span class="s2">"2"</span><span class="p">,</span> <span class="nt">"author"</span><span class="p">:</span> <span class="s2">"Jordan Walke"</span><span class="p">,</span> <span class="nt">"text"</span><span class="p">:</span> <span class="s2">"This is *another* comment"</span><span class="p">}</span>
|
|
<span class="p">]</span>
|
|
</code></pre></div><div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial13.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">{</span><span class="nx">data</span><span class="o">:</span> <span class="p">[]};</span>
|
|
<span class="p">},</span>
|
|
<span class="hll"> <span class="nx">componentDidMount</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
|
|
</span><span class="hll"> <span class="nx">url</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
|
</span><span class="hll"> <span class="nx">dataType</span><span class="o">:</span> <span class="s1">'json'</span><span class="p">,</span>
|
|
</span><span class="hll"> <span class="nx">cache</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
|
|
</span><span class="hll"> <span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">});</span>
|
|
</span><span class="hll"> <span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">),</span>
|
|
</span><span class="hll"> <span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
|
</span><span class="hll"> <span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
|
|
</span><span class="hll"> <span class="p">});</span>
|
|
</span><span class="hll"> <span class="p">},</span>
|
|
</span> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Comments</span><span class="o"><</span><span class="err">/h1></span>
|
|
<span class="o"><</span><span class="nx">CommentList</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">data</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">CommentForm</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>Here, <code>componentDidMount</code> is a method called automatically by React after a component is rendered for the first time. The key to dynamic updates is the call to <code>this.setState()</code>. We replace the old array of comments with the new one from the server and the UI automatically updates itself. Because of this reactivity, it is only a minor change to add live updates. We will use simple polling here but you could easily use WebSockets or other technologies.</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial14.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="hll"> <span class="nx">loadCommentsFromServer</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
</span> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
|
|
<span class="nx">url</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
|
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">'json'</span><span class="p">,</span>
|
|
<span class="nx">cache</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
|
|
<span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">});</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">),</span>
|
|
<span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
|
|
<span class="p">});</span>
|
|
<span class="hll"> <span class="p">},</span>
|
|
</span> <span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">{</span><span class="nx">data</span><span class="o">:</span> <span class="p">[]};</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">componentDidMount</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">loadCommentsFromServer</span><span class="p">();</span>
|
|
</span><span class="hll"> <span class="nx">setInterval</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">loadCommentsFromServer</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">pollInterval</span><span class="p">);</span>
|
|
</span> <span class="p">},</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Comments</span><span class="o"><</span><span class="err">/h1></span>
|
|
<span class="o"><</span><span class="nx">CommentList</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">data</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">CommentForm</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
|
|
<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">CommentBox</span> <span class="nx">url</span><span class="o">=</span><span class="s2">"/api/comments"</span> <span class="nx">pollInterval</span><span class="o">=</span><span class="p">{</span><span class="mi">2000</span><span class="p">}</span> <span class="o">/></span><span class="p">,</span>
|
|
</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'content'</span><span class="p">)</span>
|
|
<span class="p">);</span>
|
|
</code></pre></div>
|
|
<p>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 <code>comments.json</code> file (in the same directory as your server); within 2 seconds, the changes will show!</p>
|
|
<h3><a class="anchor" name="adding-new-comments"></a>Adding new comments <a class="hash-link" href="#adding-new-comments">#</a></h3>
|
|
<p>Now it's time to build the form. Our <code>CommentForm</code> component should ask the user for their name and comment text and send a request to the server to save the comment.</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial15.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentForm</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">form</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentForm"</span><span class="o">></span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="nx">input</span> <span class="nx">type</span><span class="o">=</span><span class="s2">"text"</span> <span class="nx">placeholder</span><span class="o">=</span><span class="s2">"Your name"</span> <span class="o">/></span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="nx">input</span> <span class="nx">type</span><span class="o">=</span><span class="s2">"text"</span> <span class="nx">placeholder</span><span class="o">=</span><span class="s2">"Say something..."</span> <span class="o">/></span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="nx">input</span> <span class="nx">type</span><span class="o">=</span><span class="s2">"submit"</span> <span class="nx">value</span><span class="o">=</span><span class="s2">"Post"</span> <span class="o">/></span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="err">/form></span>
|
|
</span> <span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div><h4><a class="anchor" name="controlled-components"></a>Controlled components <a class="hash-link" href="#controlled-components">#</a></h4>
|
|
<p>With the traditional DOM, <code>input</code> elements are rendered and the browser manages the state (its rendered value). As a result, the state of the actual DOM will differ from that of the component. This is not ideal as the state of the view will differ from that of the component. In React, components should always represent the state of the view and not only at the point of initialization.</p>
|
|
|
|
<p>Hence, we will be using <code>this.state</code> to save the user's input as it is entered. We define an initial <code>state</code> with two properties <code>author</code> and <code>text</code> and set them to be empty strings. In our <code><input></code> elements, we set the <code>value</code> prop to reflect the <code>state</code> of the component and attach <code>onChange</code> handlers to them. These <code><input></code> elements with a <code>value</code> set are called controlled components. Read more about controlled components on the <a href="/react/docs/forms.html#controlled-components">Forms article</a>.</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial16.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentForm</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="hll"> <span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="k">return</span> <span class="p">{</span><span class="nx">author</span><span class="o">:</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="s1">''</span><span class="p">};</span>
|
|
</span><span class="hll"> <span class="p">},</span>
|
|
</span><span class="hll"> <span class="nx">handleAuthorChange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">author</span><span class="o">:</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">});</span>
|
|
</span><span class="hll"> <span class="p">},</span>
|
|
</span><span class="hll"> <span class="nx">handleTextChange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">text</span><span class="o">:</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">});</span>
|
|
</span><span class="hll"> <span class="p">},</span>
|
|
</span> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">form</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentForm"</span><span class="o">></span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">input</span>
|
|
</span><span class="hll"> <span class="nx">type</span><span class="o">=</span><span class="s2">"text"</span>
|
|
</span><span class="hll"> <span class="nx">placeholder</span><span class="o">=</span><span class="s2">"Your name"</span>
|
|
</span><span class="hll"> <span class="nx">value</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">author</span><span class="p">}</span>
|
|
</span><span class="hll"> <span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleAuthorChange</span><span class="p">}</span>
|
|
</span><span class="hll"> <span class="o">/></span>
|
|
</span><span class="hll"> <span class="o"><</span><span class="nx">input</span>
|
|
</span><span class="hll"> <span class="nx">type</span><span class="o">=</span><span class="s2">"text"</span>
|
|
</span><span class="hll"> <span class="nx">placeholder</span><span class="o">=</span><span class="s2">"Say something..."</span>
|
|
</span><span class="hll"> <span class="nx">value</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">text</span><span class="p">}</span>
|
|
</span><span class="hll"> <span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleTextChange</span><span class="p">}</span>
|
|
</span><span class="hll"> <span class="o">/></span>
|
|
</span> <span class="o"><</span><span class="nx">input</span> <span class="nx">type</span><span class="o">=</span><span class="s2">"submit"</span> <span class="nx">value</span><span class="o">=</span><span class="s2">"Post"</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/form></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div><h4><a class="anchor" name="events"></a>Events <a class="hash-link" href="#events">#</a></h4>
|
|
<p>React attaches event handlers to components using a camelCase naming convention. We attach <code>onChange</code> handlers to the two <code><input></code> elements. Now, as the user enters text into the <code><input></code> fields, the attached <code>onChange</code> callbacks are fired and the <code>state</code> of the component is modified. Subsequently, the rendered value of the <code>input</code> element will be updated to reflect the current component <code>state</code>.</p>
|
|
|
|
<p>(The astute reader may be surprised that these event handlers work as described, given that the method references are not explicitly bound to <code>this</code>. <code>React.createClass(...)</code> <a href="/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation">automatically binds</a> each method to its component instance, obviating the need for explicit binding.)</p>
|
|
<h4><a class="anchor" name="submitting-the-form"></a>Submitting the form <a class="hash-link" href="#submitting-the-form">#</a></h4>
|
|
<p>Let's make the form interactive. When the user submits the form, we should clear it, submit a request to the server, and refresh the list of comments. To start, let's listen for the form's submit event and clear it.</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial17.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentForm</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">{</span><span class="nx">author</span><span class="o">:</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="s1">''</span><span class="p">};</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">handleAuthorChange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">author</span><span class="o">:</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">handleTextChange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">text</span><span class="o">:</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="hll"> <span class="nx">handleSubmit</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
|
|
</span><span class="hll"> <span class="kd">var</span> <span class="nx">author</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">author</span><span class="p">.</span><span class="nx">trim</span><span class="p">();</span>
|
|
</span><span class="hll"> <span class="kd">var</span> <span class="nx">text</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">text</span><span class="p">.</span><span class="nx">trim</span><span class="p">();</span>
|
|
</span><span class="hll"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">text</span> <span class="o">||</span> <span class="o">!</span><span class="nx">author</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="k">return</span><span class="p">;</span>
|
|
</span><span class="hll"> <span class="p">}</span>
|
|
</span><span class="hll"> <span class="c1">// TODO: send request to the server</span>
|
|
</span><span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">author</span><span class="o">:</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="s1">''</span><span class="p">});</span>
|
|
</span><span class="hll"> <span class="p">},</span>
|
|
</span> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">form</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentForm"</span> <span class="nx">onSubmit</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleSubmit</span><span class="p">}</span><span class="o">></span>
|
|
</span> <span class="o"><</span><span class="nx">input</span>
|
|
<span class="nx">type</span><span class="o">=</span><span class="s2">"text"</span>
|
|
<span class="nx">placeholder</span><span class="o">=</span><span class="s2">"Your name"</span>
|
|
<span class="nx">value</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">author</span><span class="p">}</span>
|
|
<span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleAuthorChange</span><span class="p">}</span>
|
|
<span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">input</span>
|
|
<span class="nx">type</span><span class="o">=</span><span class="s2">"text"</span>
|
|
<span class="nx">placeholder</span><span class="o">=</span><span class="s2">"Say something..."</span>
|
|
<span class="nx">value</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">text</span><span class="p">}</span>
|
|
<span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleTextChange</span><span class="p">}</span>
|
|
<span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">input</span> <span class="nx">type</span><span class="o">=</span><span class="s2">"submit"</span> <span class="nx">value</span><span class="o">=</span><span class="s2">"Post"</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/form></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>We attach an <code>onSubmit</code> handler to the form that clears the form fields when the form is submitted with valid input.</p>
|
|
|
|
<p>Call <code>preventDefault()</code> on the event to prevent the browser's default action of submitting the form.</p>
|
|
<h4><a class="anchor" name="callbacks-as-props"></a>Callbacks as props <a class="hash-link" href="#callbacks-as-props">#</a></h4>
|
|
<p>When a user submits a comment, we will need to refresh the list of comments to include the new one. It makes sense to do all of this logic in <code>CommentBox</code> since <code>CommentBox</code> owns the state that represents the list of comments.</p>
|
|
|
|
<p>We need to pass data from the child component back up to its parent. We do this in our parent's <code>render</code> method by passing a new callback (<code>handleCommentSubmit</code>) into the child, binding it to the child's <code>onCommentSubmit</code> event. Whenever the event is triggered, the callback will be invoked:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial18.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">loadCommentsFromServer</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
|
|
<span class="nx">url</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
|
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">'json'</span><span class="p">,</span>
|
|
<span class="nx">cache</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
|
|
<span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">});</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">),</span>
|
|
<span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
|
|
<span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="hll"> <span class="nx">handleCommentSubmit</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">comment</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="c1">// TODO: submit to the server and refresh the list</span>
|
|
</span><span class="hll"> <span class="p">},</span>
|
|
</span> <span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">{</span><span class="nx">data</span><span class="o">:</span> <span class="p">[]};</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">componentDidMount</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">loadCommentsFromServer</span><span class="p">();</span>
|
|
<span class="nx">setInterval</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">loadCommentsFromServer</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">pollInterval</span><span class="p">);</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Comments</span><span class="o"><</span><span class="err">/h1></span>
|
|
<span class="o"><</span><span class="nx">CommentList</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">data</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="hll"> <span class="o"><</span><span class="nx">CommentForm</span> <span class="nx">onCommentSubmit</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleCommentSubmit</span><span class="p">}</span> <span class="o">/></span>
|
|
</span> <span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>Now that <code>CommentBox</code> has made the callback available to <code>CommentForm</code> via the <code>onCommentSubmit</code> prop, the <code>CommentForm</code> can call the callback when the user submits the form:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial19.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentForm</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">{</span><span class="nx">author</span><span class="o">:</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="s1">''</span><span class="p">};</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">handleAuthorChange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">author</span><span class="o">:</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">handleTextChange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">text</span><span class="o">:</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">handleSubmit</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
|
|
<span class="kd">var</span> <span class="nx">author</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">author</span><span class="p">.</span><span class="nx">trim</span><span class="p">();</span>
|
|
<span class="kd">var</span> <span class="nx">text</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">text</span><span class="p">.</span><span class="nx">trim</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">text</span> <span class="o">||</span> <span class="o">!</span><span class="nx">author</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">onCommentSubmit</span><span class="p">({</span><span class="nx">author</span><span class="o">:</span> <span class="nx">author</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="nx">text</span><span class="p">});</span>
|
|
</span> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">author</span><span class="o">:</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="s1">''</span><span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">form</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentForm"</span> <span class="nx">onSubmit</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleSubmit</span><span class="p">}</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">input</span>
|
|
<span class="nx">type</span><span class="o">=</span><span class="s2">"text"</span>
|
|
<span class="nx">placeholder</span><span class="o">=</span><span class="s2">"Your name"</span>
|
|
<span class="nx">value</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">author</span><span class="p">}</span>
|
|
<span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleAuthorChange</span><span class="p">}</span>
|
|
<span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">input</span>
|
|
<span class="nx">type</span><span class="o">=</span><span class="s2">"text"</span>
|
|
<span class="nx">placeholder</span><span class="o">=</span><span class="s2">"Say something..."</span>
|
|
<span class="nx">value</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">text</span><span class="p">}</span>
|
|
<span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleTextChange</span><span class="p">}</span>
|
|
<span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">input</span> <span class="nx">type</span><span class="o">=</span><span class="s2">"submit"</span> <span class="nx">value</span><span class="o">=</span><span class="s2">"Post"</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/form></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div>
|
|
<p>Now that the callbacks are in place, all we have to do is submit to the server and refresh the list:</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial20.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">loadCommentsFromServer</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
|
|
<span class="nx">url</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
|
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">'json'</span><span class="p">,</span>
|
|
<span class="nx">cache</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
|
|
<span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">});</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">),</span>
|
|
<span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
|
|
<span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">handleCommentSubmit</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">comment</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="hll"> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
|
|
</span><span class="hll"> <span class="nx">url</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
|
</span><span class="hll"> <span class="nx">dataType</span><span class="o">:</span> <span class="s1">'json'</span><span class="p">,</span>
|
|
</span><span class="hll"> <span class="nx">type</span><span class="o">:</span> <span class="s1">'POST'</span><span class="p">,</span>
|
|
</span><span class="hll"> <span class="nx">data</span><span class="o">:</span> <span class="nx">comment</span><span class="p">,</span>
|
|
</span><span class="hll"> <span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">});</span>
|
|
</span><span class="hll"> <span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">),</span>
|
|
</span><span class="hll"> <span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
</span><span class="hll"> <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
|
</span><span class="hll"> <span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
|
|
</span><span class="hll"> <span class="p">});</span>
|
|
</span> <span class="p">},</span>
|
|
<span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">{</span><span class="nx">data</span><span class="o">:</span> <span class="p">[]};</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">componentDidMount</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">loadCommentsFromServer</span><span class="p">();</span>
|
|
<span class="nx">setInterval</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">loadCommentsFromServer</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">pollInterval</span><span class="p">);</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Comments</span><span class="o"><</span><span class="err">/h1></span>
|
|
<span class="o"><</span><span class="nx">CommentList</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">data</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">CommentForm</span> <span class="nx">onCommentSubmit</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleCommentSubmit</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div><h3><a class="anchor" name="optimization-optimistic-updates"></a>Optimization: optimistic updates <a class="hash-link" href="#optimization-optimistic-updates">#</a></h3>
|
|
<p>Our application is now feature complete but it feels slow to have to wait for the request to complete before your comment appears in the list. We can optimistically add this comment to the list to make the app feel faster.</p>
|
|
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// tutorial21.js</span>
|
|
<span class="kd">var</span> <span class="nx">CommentBox</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
|
|
<span class="nx">loadCommentsFromServer</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
|
|
<span class="nx">url</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
|
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">'json'</span><span class="p">,</span>
|
|
<span class="nx">cache</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
|
|
<span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">});</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">),</span>
|
|
<span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
|
|
<span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">handleCommentSubmit</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">comment</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="hll"> <span class="kd">var</span> <span class="nx">comments</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">data</span><span class="p">;</span>
|
|
</span><span class="hll"> <span class="c1">// Optimistically set an id on the new comment. It will be replaced by an</span>
|
|
</span><span class="hll"> <span class="c1">// id generated by the server. In a production application you would likely</span>
|
|
</span><span class="hll"> <span class="c1">// not use Date.now() for this and would have a more robust system in place.</span>
|
|
</span><span class="hll"> <span class="nx">comment</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
|
|
</span><span class="hll"> <span class="kd">var</span> <span class="nx">newComments</span> <span class="o">=</span> <span class="nx">comments</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="nx">comment</span><span class="p">]);</span>
|
|
</span><span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">newComments</span><span class="p">});</span>
|
|
</span> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
|
|
<span class="nx">url</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
|
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">'json'</span><span class="p">,</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="s1">'POST'</span><span class="p">,</span>
|
|
<span class="nx">data</span><span class="o">:</span> <span class="nx">comment</span><span class="p">,</span>
|
|
<span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">});</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">),</span>
|
|
<span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="hll"> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">data</span><span class="o">:</span> <span class="nx">comments</span><span class="p">});</span>
|
|
</span> <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
|
<span class="p">}.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
|
|
<span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">{</span><span class="nx">data</span><span class="o">:</span> <span class="p">[]};</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">componentDidMount</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">loadCommentsFromServer</span><span class="p">();</span>
|
|
<span class="nx">setInterval</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">loadCommentsFromServer</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">pollInterval</span><span class="p">);</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"commentBox"</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Comments</span><span class="o"><</span><span class="err">/h1></span>
|
|
<span class="o"><</span><span class="nx">CommentList</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">data</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">CommentForm</span> <span class="nx">onCommentSubmit</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleCommentSubmit</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">});</span>
|
|
</code></pre></div><h3><a class="anchor" name="congrats"></a>Congrats! <a class="hash-link" href="#congrats">#</a></h3>
|
|
<p>You have just built a comment box in a few simple steps. Learn more about <a href="/react/docs/why-react.html">why to use React</a>, or dive into the <a href="/react/docs/top-level-api.html">API reference</a> and start hacking! Good luck!</p>
|
|
|
|
|
|
<div class="docs-prevnext">
|
|
|
|
<a class="docs-prev" href="/react/docs/getting-started.html">← Prev</a>
|
|
|
|
|
|
<a class="docs-next" href="/react/docs/thinking-in-react.html">Next →</a>
|
|
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
|
|
<footer class="wrap">
|
|
<div class="left">
|
|
A Facebook & Instagram collaboration.<br>
|
|
<a href="/react/acknowledgements.html">Acknowledgements</a>
|
|
</div>
|
|
<div class="right">
|
|
© 2013–2016 Facebook Inc.<br>
|
|
Documentation licensed under <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
<div id="fb-root"></div>
|
|
|
|
<script>
|
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
|
ga('create', 'UA-41298772-1', 'facebook.github.io');
|
|
ga('send', 'pageview');
|
|
|
|
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
|
|
|
|
(function(d, s, id) {
|
|
var js, fjs = d.getElementsByTagName(s)[0];
|
|
if (d.getElementById(id)) return;
|
|
js = d.createElement(s); js.id = id;
|
|
js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.6&appId=623268441017527";
|
|
fjs.parentNode.insertBefore(js, fjs);
|
|
}(document, 'script', 'facebook-jssdk'));
|
|
|
|
docsearch({
|
|
apiKey: '36221914cce388c46d0420343e0bb32e',
|
|
indexName: 'react',
|
|
inputSelector: '#algolia-doc-search'
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|