You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
931 lines
36 KiB
931 lines
36 KiB
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<link href="./docs/assets/js/google-code-prettify/prettify.css" rel="stylesheet">
|
|
<meta charset="utf-8">
|
|
<title>React Javascript Framework</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="description" content="">
|
|
<meta name="author" content="">
|
|
|
|
<!-- Le styles -->
|
|
<link href="./docs/assets/css/bootstrap.css" rel="stylesheet">
|
|
<style type="text/css">
|
|
.hoverCardLink,
|
|
.hoverCardLink:hover,
|
|
.hoverCardLink:active {
|
|
cursor: default;
|
|
text-decoration: none;
|
|
border-bottom: 1px dotted #ba0000;
|
|
border-bottom: 1px dotted rgb(91, 116, 168);
|
|
}
|
|
body {
|
|
/*background-image: url("../../../whiteGrain.png");*/
|
|
padding-top: 60px;
|
|
padding-bottom: 40px;
|
|
}
|
|
.sidebar-nav {
|
|
padding: 9px 0;
|
|
}
|
|
</style>
|
|
<link href="./docs/assets/css/bootstrap-responsive.css" rel="stylesheet">
|
|
|
|
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
|
<!--[if lt IE 9]>
|
|
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
|
<![endif]-->
|
|
|
|
<!-- Le fav and touch icons -->
|
|
<link rel="shortcut icon" href="./docs/assets/ico/favicon.ico">
|
|
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="./docs/assets/ico/apple-touch-icon-144-precomposed.png">
|
|
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="./docs/assets/ico/apple-touch-icon-114-precomposed.png">
|
|
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="./docs/assets/ico/apple-touch-icon-72-precomposed.png">
|
|
<link rel="apple-touch-icon-precomposed" href="./docs/assets/ico/apple-touch-icon-57-precomposed.png">
|
|
</head>
|
|
|
|
<body data-spy="scroll" onload="prettyPrint()">
|
|
|
|
<div class="navbar-fixed-top navbar">
|
|
<div class="navbar-inner">
|
|
<div class="container-fluid">
|
|
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
|
<span class="icon-bar"></span>
|
|
<span class="icon-bar"></span>
|
|
<span class="icon-bar"></span>
|
|
</button>
|
|
<a style="float:right;font-weight:bold;color:black; text-shadow: 0 1px 0 rgba(255, 255, 255, .1), 0 0 30px rgba(255, 255, 255, .125)" class="brand" href="./index.html">React</a>
|
|
<div class="nav-collapse">
|
|
<ul class="nav">
|
|
<li><a href="#reactTop">React</a></li>
|
|
<li><a href="#gettingStarted">Get Started</a></li>
|
|
<li><a href="#tutorial">Tutorial</a></li>
|
|
</ul>
|
|
</div><!--/.nav-collapse -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="reactTop" class="container">
|
|
<br>
|
|
<br>
|
|
<h1 id="gettingStarted">Start Hacking <small>with React</small></h1>
|
|
<hr>
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3 style="">A Simple Example</h3>
|
|
<ul>
|
|
<li><code>@jsx React.DOM</code> enables XML syntax known as <code>jsx</code>.</li>
|
|
<li>The <code>React</code> module allows for creation and rendering of React components.</li>
|
|
<li><code>msg</code> is a React component instance, constructed using XML syntax.</li>
|
|
<li><code>React.renderComponent</code> renders the react content into the document. </li>
|
|
</ul>
|
|
<br>
|
|
<br>
|
|
<a id="behindTheScenesBtn" class="btn"><i class="icon-film"></i> Behind the Scenes</a>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 1: Simple Example of React Usage</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
/**
|
|
* @jsx React.DOM
|
|
*/
|
|
var React = require('React');
|
|
var msg =
|
|
<div class="outerDiv">
|
|
<span>hello</span>
|
|
</div>;
|
|
React.renderComponent(msg, document.getElementById('someId'));</pre>
|
|
</div>
|
|
|
|
</div>
|
|
<br>
|
|
<br>
|
|
<div id="behindTheScenes" class="row">
|
|
<div class="span6">
|
|
<h3>Behind the Scenes</h3>
|
|
<p>
|
|
The previous example was very straightforward except for the use of
|
|
XML syntax. The inclusion of <code>@jsx React.DOM</code> accomplishes
|
|
two things.
|
|
<ol>
|
|
<li>Tells the build system to compile XML syntax into standard
|
|
javascript function calls.
|
|
</li>
|
|
<li>
|
|
Ensures that <code>div</code> and <code>span</code> are
|
|
functions that are in scope. In fact, all standard DOM tags
|
|
(such as <code>img</code> and <code>ul</code> are also treated
|
|
this way).
|
|
</li>
|
|
</ol>
|
|
</p>
|
|
<p>
|
|
Obviously, javascript isn't the most attractive way to specify
|
|
declarative structures. The XML syntax will be used for the
|
|
remainder of this tutorial. Additionally, require calls and calls to
|
|
<code>React.renderComponent</code> will be ommited from
|
|
examples.
|
|
</p>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 2: Example of compiler output</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
/**
|
|
* @jsx React.DOM
|
|
*/
|
|
var React = require('React');
|
|
var div = React.DOM.div;
|
|
var span = React.DOM.span;
|
|
var msg =
|
|
div({
|
|
className:"outerDiv",
|
|
children: [
|
|
span({
|
|
children: ['hello']
|
|
})
|
|
]
|
|
});
|
|
React.renderComponent(msg, document.getElementById('someId'));
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3 style="">Mobile Development</h3>
|
|
If developing for mobile, ensure that React is listening to touch
|
|
events <i>before</i> performing rendering. This only needs to be done
|
|
once. Everything else is exactly as it would be on desktop.
|
|
<br>
|
|
<br>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 2.5: Supporting mobile</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
React.initializeTouchEvents(true);
|
|
React.renderComponent(yourComponent, document.getElementById('someId')); </pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3 style="">JSX Development Environment</h3>
|
|
<ul>
|
|
<li><b>Vim</b> already supports the <code>jsx</code> syntax out of the box.</li>
|
|
<li>If you prefer <b>Emacs</b>, <a href="http://code.google.com/p/js2-mode/">JS2 mode</a> works well. </li>
|
|
<li>For <a href="Sublime Text" href="http://www.sublimetext.com/">Sublime Text</a>, you can use the
|
|
excellent <a href="http://home.fburl.com/~yungsters/facelime/#configuration">Facelime</a>
|
|
tools which adds syntax highlighting and inline editor linting of <code>jsx</code>.
|
|
</li>
|
|
<li>Arc lint correctly supports <code>jsx</code> syntax.</li>
|
|
</ul>
|
|
<br>
|
|
<br>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<br>
|
|
<br>
|
|
<h1>Types of Components <small>application building blocks</small></h1>
|
|
<hr>
|
|
|
|
<!-- <div class="row"> -->
|
|
<!-- <div class="span6"> -->
|
|
<!-- <h2 style="font-weight:500">Types of Components</h2> -->
|
|
<!-- There are two subclasses of <code>ReactComponent</code> -->
|
|
<!-- <ul> -->
|
|
<!-- <li> <code>ReactDOMComponent</code>: Wrappers around DOM elements such as <code>div</code> and <code>span</code>.</li> -->
|
|
<!-- <li> <code>ReactCompositeComponent</code>: Higher level (custom) components. We haven't seen these yet. </li> -->
|
|
<!-- </ul> -->
|
|
<!-- Note that React seldom <a class="hoverCardLink"" href="#hoverCardLink" id="inheritancenote">uses inheritance.</a> -->
|
|
<!-- </div> -->
|
|
<!-- <div class="span6"> -->
|
|
<!-- <h6><small>Fig 3: Hierarchy of components</small></h6> -->
|
|
<!-- <b>insert diagram</b> -->
|
|
<!-- </div> -->
|
|
<!-- </div> -->
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>DOM Components <small>such as <code>div</code> and <code>span</code>.</small>
|
|
</h3>
|
|
DOM components are always in scope when including <code>@jsx
|
|
React.DOM</code> in the first docblock comment. All DOM components
|
|
support <a href="#childrenexplain" class="hoverCardLink"
|
|
id="childrenexplain">children</a> in addition to standard DOM
|
|
attributes <code>class</code>, <code>href</code>, etc. The only thing to
|
|
remember, is that DOM attributes should be expressed in camelCase (<code>onClick</code>).
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 4: DOM Component attributes</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
var fbUrl = "www.facebook.com";
|
|
var btn = <a href={fbUrl} class="butButton"> Visit Facebook </a>;
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>Composite Components <small>such as <code>Typeahead</code> and <code>LeftNav</code></h3>
|
|
<p>
|
|
<code>ReactCompositeComponent</code>s are "custom" components.
|
|
Composite components are not automatically "in scope" like
|
|
<code>ReactDOMComponent</code>s. The tag name will need to be
|
|
defined as a variable in the scope. By convention, each
|
|
<code>ReactCompositeComponent</code> is a commonJS module.
|
|
</p>
|
|
<br>
|
|
<p><span class="label label-important">Remember:</span> Composite
|
|
components must be in scope before use.</p>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 5: Usage of COMPOSITE COMPONENT</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
// Suppose Typeahead is an instnace of ReactCompositeComponent
|
|
var Typeahead = require('Typeahead');
|
|
|
|
// Typeahead has chosen to accept a "selected" attribute
|
|
// and children.
|
|
var myTypeahead=
|
|
<Typeahead selected="jordanjcw" >
|
|
{something.dataset}
|
|
</Typeahead>;
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<br>
|
|
<br>
|
|
<h1 id="tutorial">Let's Build a Component <small>from scratch</small></h1>
|
|
<hr>
|
|
<div class="row">
|
|
<div class="span6">
|
|
<p>
|
|
The following tutorial shows you how to define a new component type
|
|
called <code>LikeToggler</code>.
|
|
The <code>LikeToggler</code> will render an image and allow the user to
|
|
toggle the like status on the image. See Image 1 to the right for a
|
|
screenshot of the final result.
|
|
</p>
|
|
<p>To create a new component type, we must specify: </p>
|
|
<ul>
|
|
<li>
|
|
The structure of the component - what is it composed of, and how it
|
|
should be rendered.
|
|
</li>
|
|
<li>
|
|
How it encapsulates state, and how that state changes over time.
|
|
</li>
|
|
<li>
|
|
The way in which user interactions may influence state changes.
|
|
</li>
|
|
</ul>
|
|
<p><span class="label label-info">Note:</span> React favors composition
|
|
over inheritance as a means of abstraction.</p>
|
|
</p>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Image 1: Final Result</small></h6>
|
|
<img style="padding-right:10px" class="thumbnail" src="./img/LikeToggler.png" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- <div class="row"> -->
|
|
<!-- <div class="span6"> -->
|
|
<!-- </div> -->
|
|
<!-- <div class="span6"> -->
|
|
<!-- </div> -->
|
|
<!-- </div> -->
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>1. Begin the tutorial</h3>
|
|
<p>
|
|
All of the plumbing for this tutorial has been set up for you in
|
|
www/trunk. Simply edit the main tutorial javascript file and refresh
|
|
your browser. (See Figure 6 to the right).
|
|
</p>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 6: Editing the tutorial</small></h6>
|
|
<pre class="prettyprint linenums">vim ~/www/html/js/components/ReactTutorial/ReactTutorial.js
|
|
Open http://yourSandbox.facebook.com/intern/reacttutorial</pre>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>2. A New Component Shell</h3>
|
|
<p>
|
|
Here, we create a new component called <code>LikeToggler</code> by
|
|
making a call to <code>React.createClass</code>. We pass a
|
|
javascript object that describes the methods to include in the new
|
|
class. <code>render</code> is the most important method, and is the
|
|
only one required. It <i>describes</i> the structure of your
|
|
component.
|
|
</p>
|
|
<p><span class="label label-important">Remember:</span> <code>render</code> should never have side effects.</p>
|
|
<p><span class="label label-important">Remember:</span>
|
|
When returning <code>jsx</code> blocks, parenthesis guard
|
|
against <a class="hoverCardLink" id="asiexplain"
|
|
href="#asiexplain">ASI</a>.</p>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 7: basic component definition</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
var LikeToggler = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<div>
|
|
Welcome to the tutorial. Implement LikeToggler here!
|
|
</div>
|
|
);
|
|
}
|
|
});</pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>3. Add Richer Structure</h3>
|
|
Here, we've added a header component and a picture of Boo. We've
|
|
also placed a class on the outermost div to give the component some
|
|
style. In your tutorial file, change your <code>render</code>
|
|
function to match Figure 8.
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 8: Richer structure</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
var LikeToggler = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<div class="LikeToggler">
|
|
<h5>Toggle your like.</h5>
|
|
<img src="https://graph.facebook.com/boo/picture" />
|
|
</div>
|
|
);
|
|
}
|
|
});</pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>4. Add Statefulness</h3>
|
|
<p>
|
|
Let's make our app interactive! We'll allow the user to "Like" Boo
|
|
through our component's interface. In order to do so, we'll want to
|
|
track that state in our component internally.
|
|
</p>
|
|
Add a method called <code>getInitialState</code> to your component.
|
|
<code>getInitialState</code> should return a javascript object that
|
|
represents your component's initial state. We'll return an object
|
|
with <code>likes</code> set to <code>false</code> to indicate that
|
|
the user does not initially like Boo.
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 9: Beginning statefulness</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
var LikeToggler = React.createClass({
|
|
getInitialState: function() { // <--New method here
|
|
return {likes: false};
|
|
},
|
|
render: function() {
|
|
return (
|
|
<div class="LikeToggler">
|
|
<h5>Toggle your like.</h5>
|
|
<img src="https://graph.facebook.com/boo/picture" />
|
|
</div>
|
|
);
|
|
}
|
|
});</pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>5. Set Up User Interactions.</h3>
|
|
<ul>
|
|
<li>All DOM components support attributes and event handlers just as
|
|
you would expect (but are specified in the camelCase form).</li>
|
|
<li>
|
|
Add a new like toggler <code>span</code> in your rendered output.
|
|
</li>
|
|
<li>
|
|
Add a new <code>div</code> in your rendered output to display the
|
|
current like status.
|
|
</li>
|
|
<li>
|
|
Add a new member function that will handle the click on that new
|
|
like toggler. Call this method <code>doToggle</code>.
|
|
</li>
|
|
<li>
|
|
Set the <code>onClick</code> attribute of the <code>span</code> to
|
|
be the new member.
|
|
</li>
|
|
<li>
|
|
Place an alert inside of the <code>doToggle</code> handler to
|
|
confirm that your click is wired up correctly.
|
|
</li>
|
|
</ul>
|
|
<p><span class="label label-important">Remember:</span> Always specify DOM attributes in their camelCase form.</p>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 10: Setting up user interactions </small></h6>
|
|
<pre class="prettyprint linenums">
|
|
var LikeToggler = React.createClass({
|
|
getInitialState: function() {
|
|
return {likes: false};
|
|
},
|
|
doToggle: function(event) {
|
|
// What shall we do here?
|
|
},
|
|
render: function() {
|
|
return (
|
|
<div class="LikeToggler">
|
|
<h5>Toggle your like.</h5>
|
|
<img src="https://graph.facebook.com/boo/picture" />
|
|
<div class="btn" onClick={this.doToggle}>
|
|
Like Boo
|
|
</div>
|
|
<div></div>
|
|
</div>
|
|
);
|
|
}
|
|
});</pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>6. Change State.</h3>
|
|
<p>
|
|
We need to accomplish the following when the user clicks.
|
|
</p>
|
|
<ul>
|
|
<li>Toggle our internal state field's <code>likes</code> field.</li>
|
|
<li>Change the content of the toggler <code>div</code> from
|
|
"Like Boo" to "Unlike Boo"</li>
|
|
<li>Change the content of the <code>span</code> from empty
|
|
to "You like this."</li>
|
|
</ul>
|
|
<p>You might be tempted to search for the DOM nodes whos content you
|
|
wish to change, and force them to change. However, React provides a
|
|
more powerful abstraction to help you express the dynamics of changing
|
|
content over time. In react, we change our state fields via a call to
|
|
<code>this.setState</code>. Then, we express <code>render</code>
|
|
as a function of <code>this.state</code> at <i>all points in time</i>
|
|
- for an <i>arbitrary</i> state. Nothing else is needed!</p>
|
|
|
|
<b><p>Here's how that plays out in our example:</p></b>
|
|
<p>
|
|
First, We set our next state's <code>likes</code> field to an
|
|
inversion/toggle of our current <code>likes</code> (Line 8).
|
|
Then, we make our like toggler button's content is an expression
|
|
that is a function or an <i>arbitrary</i> state:
|
|
</p>
|
|
<pre class="prettyprint linenums:14">
|
|
<div class="btn" onClick={this.doToggle}>
|
|
{this.state.likes ? 'Unlike Boo' : 'Like Boo'}
|
|
</div>
|
|
</pre>
|
|
<p>
|
|
Finally, we do the same with the <code>span</code>'s content
|
|
</p>
|
|
<pre class="prettyprint linenums:13">
|
|
<span>{this.state.likes ? 'You Like This.' : ''}</span>
|
|
</pre>
|
|
React guarantees that when state is updated, these expressions
|
|
will be reevaluated and the underlying DOM structures will be <a
|
|
id="reconcilexplain" class="hoverCardLink">reconciled</a>.
|
|
To be clear, you can put <i>any</i> expression in terms of
|
|
<code>this.state</code> inside of <code>render</code>. There are
|
|
essentially <b>no</b> limitations. Consider the
|
|
<code>render</code> function to be a constraint that you specify
|
|
and that React will <b>always</b> satisfy.
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 11: Changing State </small></h6>
|
|
<pre class="prettyprint linenums">
|
|
var LikeToggler = React.createClass({
|
|
getInitialState: function() {
|
|
return {likes: false};
|
|
},
|
|
doToggle: function(event) {
|
|
this.setState({likes: !this.state.likes});
|
|
},
|
|
render: function() {
|
|
return (
|
|
<div class="LikeToggler">
|
|
<h5>Toggle your like.</h5>
|
|
<img src="https://graph.facebook.com/boo/picture" />
|
|
<span>{this.state.likes ? 'You Like This.' : ''}</span>
|
|
<div class="btn" onClick={this.doToggle}>
|
|
{this.state.likes ? 'Unlike Boo' : 'Like Boo'}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
});</pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<br>
|
|
<br>
|
|
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>7. Add attributes <small>or <i>props</i></small></h3>
|
|
<p>
|
|
There's something lacking from our <code>LikeToggler</code>
|
|
component. Components such as <code>div</code> and <code>span</code>
|
|
accept attributes (such as <code>href</code> and
|
|
<code>class</code>), but currently, our component is instantiated as
|
|
follows, without attributes:
|
|
</p>
|
|
<pre class="prettyprint linenums">var myLikeToggler = <LikeToggler />;</pre>
|
|
<p>
|
|
Now suppose we want to control the entity being liked.
|
|
</p>
|
|
<pre class="prettyprint linenums">var myLikeToggler =
|
|
<LikeToggler
|
|
name="Boo"
|
|
imgSrc="http://graph.facebook.com/boo/picture"
|
|
/>;</pre>
|
|
</p>
|
|
<p>
|
|
This is extremely easy to do! Inside of the <code>render</code>
|
|
method, all attributes are accessible through a special member called
|
|
<code>this.props</code>. See the Figure 12 for the complete component.
|
|
</p>
|
|
<p>
|
|
It's worth taking a close look at the last <code>span</code>'s
|
|
content. Recognize how the content depends on two separate pieces of
|
|
data, from two completely different locations (<code>props</code>
|
|
and <code>state</code>). <i>Any</i> time either of these data
|
|
change, the content of that <code>span</code> will always be
|
|
reconciled to the expression specified.
|
|
</p>
|
|
<pre class="prettyprint linenums:14">
|
|
<div class="btn" onClick={this.doToggle}>
|
|
{(this.state.likes ? 'Unlike ' : 'Like ') + this.props.name}
|
|
</div>
|
|
</pre>
|
|
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 12: Supporting Attributes</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
var LikeToggler = React.createClass({
|
|
getInitialState: function() {
|
|
return {likes: false};
|
|
},
|
|
doToggle: function(event) {
|
|
this.setState({likes: !this.state.likes});
|
|
},
|
|
render: function() {
|
|
return (
|
|
<div class="LikeToggler">
|
|
<h5>Toggle your like.</h5>
|
|
<img src={this.props.imgSrc} />
|
|
<span>{this.state.likes ? 'You Like This.' : ''}</span>
|
|
<div class="btn" onClick={this.doToggle}>
|
|
{(this.state.likes ? 'Unlike ' : 'Like ') + this.props.name}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
});</pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<h1>Properties and State <small>ownership of information</small></h1>
|
|
<hr>
|
|
<div class="row">
|
|
<div class="span6">
|
|
<p><span class="label label-info">Note:</span> The terms <code>attributes</code> and <code>props</code> used interchangably.</p>
|
|
<h3>Ownership:</h3>
|
|
<p>
|
|
When you look at <code>render</code>, anywhere you see tags
|
|
<code><...></code> there exists an implication of "ownership".
|
|
Meaning that whatever instance <code>render</code>s, also "owns"
|
|
those components that are rendered. For example, in Figure 13, we
|
|
define a new component type <code>LikeTogglerWrapper</code> that is
|
|
<i>composed</i> of the <code>LikeToggler</code> that we previously
|
|
defined.
|
|
The <code>LikeTogglerWrapper</code> instance clearly <i>owns</i> the
|
|
<code>LikeToggler</code> component. The
|
|
<code>LikeTogglerWrapper</code> is only thing thing that determines
|
|
the <code>props</code> (or <code>attributes</code>) of the
|
|
<code>LikeToggler</code>. Furthermore, it is the only thing that
|
|
determines its very existence.
|
|
</p>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 13: new component</small></h6>
|
|
<pre class="prettyprint linenums">
|
|
var LikeTogglerWrapper = React.createClass({
|
|
render: function() {
|
|
return (
|
|
<LikeToggler
|
|
imgSrc="https://graph.facebook.com//picture"
|
|
name="jwalke"
|
|
/>
|
|
);
|
|
}
|
|
});</pre>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="span6">
|
|
<h3>Control Of Information:</h3>
|
|
<p>
|
|
|
|
<p>Clearly, our new component is somehow "in charge" of the
|
|
<code>LikeToggler</code>, so it makes sense to use the term "owner".
|
|
However, there's still one thing it's not in charge of - the
|
|
internal <i><code>state</code></i> of the <code>LikeToggler</code>.
|
|
<code>state</code> and <code>props</code> are both simple packages
|
|
of information, but they are distinct in one <b>critical</b> aspect
|
|
- <b><i>control</i></b>.
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
You control your <code>this.state</code>. You are the only one that
|
|
should ever update <code>this.state</code>. You never need to ask
|
|
permission to update your own state because you are in control of
|
|
it.
|
|
</li>
|
|
<li>
|
|
You do <i>not</i> control your <code>this.props</code>. Your
|
|
props are controlled by the same entity that instantiated
|
|
<i>you</i> - that is to say that your <code>this.props</code> are
|
|
controlled by your <i>owner</i>.
|
|
Therefore, you should never update your own <code>this.props</code>.
|
|
</li>
|
|
</ul>
|
|
<p>
|
|
The description of <code>this.state</code>
|
|
describes traditional encapsulation. But the description of
|
|
<code>this.props</code> is less familiar. We've described
|
|
<code>this.props</code> as public, but in a more restricted way than
|
|
in traditional OO design. Our props <i>can</i> be controlled from outside
|
|
of our component instance, because they can <i>only</i> be controlled from
|
|
outside of our component instance, by the owner of <i>us</i>. See
|
|
Figure 14 for an illustration of data flow, ownerhip and control.
|
|
</p>
|
|
<p>
|
|
These two conventions ensure that all data in the system has a
|
|
single owner. If you wish to control information that you do not
|
|
own, you must find a way to inform the <i>owner</i> of that
|
|
information that you wish to change it. In other programming
|
|
paradigms, these authoritatively owned packages of information may
|
|
be refered to as <i>models</i>.
|
|
</p>
|
|
<br>
|
|
<p>
|
|
<span class="label label-important">Remember:</span>
|
|
A component instance must be the only one to update its own
|
|
<code>this.state</code> via a call to
|
|
<code>this.setState({..})</code> and nothing else should update
|
|
its <code>this.state</code>.
|
|
</p>
|
|
<p>
|
|
<span class="label label-important">Remember:</span>
|
|
A component must never update its own <code>this.props</code>. Only
|
|
a component's "owner" (or the Reactive system) should ever
|
|
update its props.
|
|
</p>
|
|
<h3>Streams:</h3>
|
|
<p>
|
|
Examine Figure 14. It helps to think of <code>this.props</code> and
|
|
<code>this.state</code> as streams of information that your
|
|
<code>render</code> function operates on in order to return your
|
|
component's structure. <code>render</code> always
|
|
sees the freshest values of these streams. You do not need to
|
|
perform any setup to make this happen. You do not need to subscribe
|
|
to any changes. The React core makes sure that
|
|
<code>render</code> correctly describes your component's structure
|
|
whenever <code>this.props</code> or <code>this.state</code> may have
|
|
changed.
|
|
</p>
|
|
<h3>Flow Of Information:</h3>
|
|
<p>
|
|
We said that <code>render</code> always "sees the freshest values"
|
|
of <code>this.props</code> and <code>this.state</code>, but how does
|
|
this
|
|
happen? In particular, how does a component always see the freshest
|
|
values of <code>this.props</code>? If a component cannot update its
|
|
own <code>this.props</code>, then who does? The answer is that
|
|
changes to <code>this.props</code> will be the result of a call to
|
|
<code>setState()</code> at a higher level in the component
|
|
hierarchy. From the point of state update, the reactive system will
|
|
ensure that the component subtree is brought up to date by updating
|
|
the <code>props</code> of components below it in the hierarchy.
|
|
</p>
|
|
<p>
|
|
There are some exceptional cases, where it doesn't make sense to
|
|
merely rely on state changes to update props, but those cases are
|
|
rare. In those cases, React allows a way to attach a reference
|
|
handle to individual components returned from <code>render</code>
|
|
and to directly tell that component to update its props, bypassing
|
|
the standard reactive data flow. In doing so, we're not violating
|
|
the rules mentioned above. The component that specifies the
|
|
reference handles, and invokes `updateProps` is the rightful "owner"
|
|
of the referenced component and has full authority to update the
|
|
props directly.
|
|
</p>
|
|
<p><span class="label label-info">Note:</span> This will be
|
|
further documented in a new tutorial section discussing "refs" (not
|
|
yet written).</p>
|
|
</p>
|
|
</div>
|
|
<div class="span6">
|
|
<h6><small>Fig 14: Control of information</small></h6>
|
|
<img style="z-index:-999; position: relative; top: -40px" src="./img/ReactDataDiagram.png" />
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<h1>Recap <small>memorize this</small></h1>
|
|
<hr>
|
|
<div class="row">
|
|
<div class="span12">
|
|
<ul>
|
|
<li>
|
|
Require other Composite Components by <code>require</code>ing
|
|
them. DOM components (such as <code><div /></code>) are
|
|
always in scope and do not need to be <code>require</code>d.
|
|
</li>
|
|
<li>
|
|
DOM components support the familiar attributes, but in camelCase form (such as <code>onClick</code>).
|
|
</li>
|
|
<li>
|
|
Use <code>React.createClass</code> to create a new custom component class.
|
|
</li>
|
|
<li>
|
|
Specify the visual structure of your component in
|
|
<code>render</code> as a function of an <i>arbitrary</i>
|
|
<code>this.state</code> and <code>this.props</code>.
|
|
</li>
|
|
<li>
|
|
Inside of <code>render</code>, you observe attributes by
|
|
referencing <code>this.props.attributeName</code>.
|
|
</li>
|
|
<li>
|
|
Inside of <code>render</code>, you observe internal state by
|
|
referencing <code>this.states.stateFieldName</code>.
|
|
</li>
|
|
<li>
|
|
<code>render</code> always sees the most up-to-date values for
|
|
<code>this.state</code> and <code>this.props</code>.
|
|
</li>
|
|
<li>
|
|
Render should <b>never</b> have side effects.
|
|
</li>
|
|
<li>
|
|
Perform state updates via calls to <code>this.setState({...})</code>.
|
|
</li>
|
|
<li>
|
|
Only <i>you</i> may update your <code>this.state</code>.
|
|
</li>
|
|
<li>
|
|
You may never update your own <code>this.props</code>.
|
|
</li>
|
|
<li>
|
|
<code>this.state</code> should only ever contain serializable data (think "JSON")
|
|
and you should never stuff react component instances into
|
|
<code>this.state</code>.
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<hr>
|
|
</div><!--/.fluid-container-->
|
|
|
|
<!-- Le javascript
|
|
================================================== -->
|
|
<!-- Placed at the end of the document so the pages load faster -->
|
|
<script src="./docs/assets/js/jquery.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-transition.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-alert.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-modal.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-dropdown.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-scrollspy.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-tab.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-tooltip.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-popover.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-button.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-collapse.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-carousel.js"></script>
|
|
<script src="./docs/assets/js/google-code-prettify/prettify.js"></script>
|
|
<script src="./docs/assets/js/bootstrap-typeahead.js"></script>
|
|
|
|
<script type="text/javascript" charset="utf-8">
|
|
$('#inheritancenote').popover({
|
|
trigger: 'hover',
|
|
title: 'Inheritance',
|
|
content: 'React does not encourage use of inheritance at the '+
|
|
'application layer, and seldom uses inheritance in the core ' +
|
|
'framework. Instead, React encouranges the functional ' +
|
|
'style where possible. However, for the sake of discussion, ' +
|
|
'it helps to think of the types of components as being in ' +
|
|
'a hierarchy.'
|
|
})
|
|
$('#asiexplain').popover({
|
|
trigger: 'hover',
|
|
title: 'Automatic Semicolon Insertion',
|
|
content: "When you type return followed by a newline, javascript will insert a semicolon after \"return\", causing you to return undefined. The <code>jsx</code> syntax does't change how javascript works here, so you need to guard return values on new lines by grouping them in parenthesis, just like you\'re used to doing in javascript."
|
|
})
|
|
$('#childrenexplain').popover({
|
|
trigger: 'hover',
|
|
title: 'Children and Attributes',
|
|
content: 'Children could be thought of as an attribute as well. In the <code>jsx</code> syntax, what you place between the open and close tags specify children attributes.'
|
|
})
|
|
$('#reconcilexplain').popover({
|
|
trigger: 'hover',
|
|
title: 'Reconciliation',
|
|
content: "In order to reconcile efficiently, React employs a couple of strategies. <ul><li>React may know that only certain regions of the page may need to be reconciled so it only searches for changes from those points.</li><li>React can traverse large search spaces quickly quickly because it searches lightweight javascript object graphs as opposed to heavyweight DOM trees.</li><li>These reconciliation strategies are abstracted away so that we can innovate new reconciliation algorithms that are highly tuned for certain critical operations (such as scrolling).</li><li>The largest benefit is that, as an app developer, you\'ll never need to worry about these details because React handles this for you. Application speed will continue to increase as core framework engineers innovate on these algorithms.</li>"
|
|
})
|
|
$('#behindTheScenes').hide()
|
|
$('#behindTheScenesBtn').click(function() {
|
|
$('#behindTheScenesBtn').hide();
|
|
$('#behindTheScenes').fadeIn();
|
|
});
|
|
$('#navbar').scrollspy()
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|