React Tutorial
Giuseppe Attardi
Università di Pisa
What is React
React is a JavaScript library for creating user interfaces
Simple
– React automatically manages all UI
updates when underlying data changes
Components
– React reusable components facilitate
code reuse, testing, and separation of
concerns
Design Features
React is not a MVC framework
No templates
– UI is made of components
– React uses a real, full featured
programming language to render views
Virtual DOM
– lightweight description of the DOM
Tier 1: browser Tier 3
MVC
local model
controller view
Web server
model controller
view
AJAX Web server Tier 3
model controller
view
React: browser
model controller
view
No MVC, just V
In traditional MVC different parts of the UI talk via events, with a controller receiving all the
user inputs, manipulating the models if needed and then calling the views and telling them to re-render if necessary.
In React, when a user interaction occurs, everything is re-rendered
Separation between code and presentation vanishes (again …)
Components are single units, they can be instantiated and moved without having to reconnect them to handlers (e.g. in
jQuery.readyFunction)
Virtual DOM
Pure JS lightweight description of the DOM
Components keep a state, avoiding storing the state in the DOM
Incremental updates
– The data returned from render is neither a string nor a DOM node -- it's a virtual DOM representing what the DOM should be
– reconciliation
Exaxmple: Reconciliation
class TextBoxList extends React.Component { constructor() {
super();
this.state = {count: 1};
}
add = () => {
this.setState({count: this.state.count + 1});
};
render() {
var items = [];
for (var i = 0; i < this.state.count; i++) {
items.push(<li><input type="text" placeholder="change me!" /></li>);
}
return ( <ul>
{items}
<input type="button" value="Add an item" onClick={this.add} />
</ul>
);
}}
Example: Render
React.render(
<div>
<p>Every time you add a new text box to the list, we "re-render" the whole list, but any text entered in the text boxes is left untouched
because React is smart enough to just append the new text box instead of
blowing away the old DOM nodes.</p>
<TextBoxList />
</div>, document.body);
Incremental update implementation
When a component is first initialized, the render method is called, generating a
lightweight representation of the view
From that representation, a string of markup is produced, and injected into the document
When data changes, the render method is called again
In order to perform updates efficiently, the React engine diff the return value from the previous call to render with the new one, and generates a minimal set of changes to be
applied to the DOM
React Render
Rendering is done in two steps:
1.
Virtual DOM render: when render method called it returns a new virtual
dom structure of the component.
This render method is called always by setState(). There is no optimization here.
2.
Native DOM render: React changes real DOM nodes in your browser only if they were changed in the Virtual DOM and as little as needed, optimizing real DOM
mutation and making React fast.
React
React JSFiddle
React Tutorial
JSX
<div className="red">Children Text</div>;
React.createElement("div", { className: "red" },
"Children Text");
JSX is a JavaScript syntax extension that looks similar to XML
<MyCounter count={3 + 5} />;
React.createElement(“MyCounter”, { count: 3 + 5 });
className not class, reserved word in JS
JSX
var scores = { player1: 2, player2: 5 };
<Dashboard data-index="2">
<h1>Scores</h1>
<Scoreboard className="results" scores={scores} />
</Dashboard>;
React.createElement(“Dashboard”, { "data-index": "2" },
React.createElement("h1", null, "Scores"), React.createElement(”Scoreboard”, {
className: "results", scores: scores }) );
Transform
Test JSX transformation to
JavaScript at Babel REPL
Components
var MessageComponent = React.createClass({
render: function() {
return <div>{this.props.message}</div>;
} });
ReactDOM.render(
<MessageComponent message="Hello!" />, document.body
);
They must implement the function render
Props
When a component is rendered, it can access its attributes using
this.props.
<div>{this.props.message}</div>;
Exercise
var VacancySign = null;
ReactDOM.render(
<div>Replace me</div>,
document.getElementById('container') );
The component VacancySign should render a div with either the text "Vacancy" or "No
Vacancy" depending on the prop hasVacancy.
View Solution
Events
var BannerAd = React.createClass({
onBannerClick: function(evt) { // codez to make the moneys },
render: function() {
// Render the div with an onClick prop (value is a function) return <div onClick={this.onBannerClick}>Click Me!</div>;
} });
Exercise
var ChildComponent = React.createClass({
render: function() { return <div>
<button>Do Magic</button> // invoke performMagic in parent </div>; }
});
var ParentComponent = React.createClass({
performMagic: function() { alert('TAADAH!'); },
render: function() { return <div> <ChildComponent /></div>; } });
ReactDOM.render( <ParentComponent />, document.getElementById('container') );
View Solution
State
A state is internal and controlled by the component itself while props are external and controlled by whatever renders the component.
See example.
Like Button
var LikeButton = React.createClass({
getInitialState: function() { return { liked: false }; },
handleClick: function(event) { this.setState({liked: !this.state.liked}); }, render: function() {
var text = this.state.liked ? 'like' : ‘might like';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
} });
ReactDOM.render(
<LikeButton />,
document.getElementById('example') );
API
getInitialState: function()
– returns dictionary
this.state
this.setState
– merges key/values into state
– triggers render()
Conclusions
React JS unifies behavior and
representation in single units called components
Code generation in JSX is exploited to
provide a DSL for expressing elements of the UI
Pure JavaScript solution, without templating engine
Programmer is in full control of the UI
Components will eventually become part
of browser capabilities
ChatRoom Client
var UsersList = React.createClass({
render() { return (
<div className='users'>
<h3> Online Users </h3>
<ul> {
this.props.users.map((user, i) => { return (<li key={i}> {user} </li>); })
}</ul>
</div>
);
}});
var Message = React.createClass({
render() { return (
<div className="message">
<strong>{this.props.user} :</strong>
<span>{this.props.text}</span> </div>
);
}});
SocketIo
var app = express();
var server = http.createServer(app);
/* Socket.io Communication */
var io = require('socket.io').listen(server);
io.sockets.on('connection', socket);
/* Start server */
server.listen(app.get('port'), function (){
console.log('Express server listening on port %d in
%s mode',
app.get('port'),
app.get('env'));});
ChatApp
var ChatApp = React.createClass({
getInitialState() {
return {users: [], messages:[], text: ''};
},
componentDidMount() { socket.on('init', this._initialize);
socket.on('send:message',
this._messageRecieve); socket.on('user:join', this._userJoined); socket.on('user:left', this._userLeft); socket.on('change:name', this._userChangedName);
},
MessageReceive
_messageRecieve(message) {
var {messages} = this.state;
messages.push(message);
this.setState({messages});},
Render
render() { return ( <div>
<UsersList users={this.state.users}/>
<MessageList messages={this.state.messages}/>
<MessageForm
onMessageSubmit={this.handleMessageSubmit}
user={this.state.user} />
<ChangeNameForm
onChangeName={this.handleChangeName} />
</div>
);
}});