React
Summary
- What
- Who
- Why
- How
- Code examples
- Some thougts
What
- Library for creating user interfaces
- Renders UI and responds to events
- V in the MVC
- Stack independent
Who
- Born at Facebook Ads Org
- Decoupled from Facebook stack to be used by Instagram
- Open source
Why
- Classic MVC
- "View model" tightly couples controllers to templates
- Templates separate technologies, not concerns
- Developers are forced to separate application concerns in a bad way
- Framework cannot know how to separate components - should be the developer
Why
- Reacting to changes in the UI is hard
- So much state and UI elements
- Data changing
- We all miss the 90's!
Why
- Complexity increases with:
- Number of developers
- UI itself
- Imagine the complexity of Facebook
How
- Build components, not templates
- Components know how to render themselves
- Separation of concerns
- Yes, we're talking about mixing markup and display logic
var CommentForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var author = React.findDOMNode(this.refs.author).value.trim();
var text = React.findDOMNode(this.refs.text).value.trim();
if (!text || !author) {
return;
}
this.props.onCommentSubmit({author: author, text: text});
React.findDOMNode(this.refs.author).value = '';
React.findDOMNode(this.refs.text).value = '';
return;
},
render: function() {
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="Your name" ref="author" />
<input type="text" placeholder="Say something..." ref="text" />
<input type="submit" value="Post" />
</form>
);
}
});
How
-
Re-render on every update
- When data changes, components are re-rendered
- Easy and intuitive to the developer
- But...
- You can't just throw out the DOM!
- Slow, flash effect, scroll position...
How
-
Virtual DOM
- Makes re-render extremely fast
- So, on every update
-
React builds a new virtual DOM subtree
-
Diffs it with the old one
-
Computes the minimal set of DOM mutations and puts them in a queue
-
And batch executes all updates
-
Virtual DOM
App
Virtual Dom
DOM
----------->
----------->
<-----------
<-----------
builds/modifies
builds/modifies
events
events
React key principles
- Components, not templates
- Re-render, don't mutate
- Virtual DOM is simple and fast
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Hello React</title>
<script src="https://fb.me/react-0.13.3.js"></script>
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
</head>
<body>
<div id="content"></div>
<script type="text/jsx">
// Your code here
</script>
</body>
</html>
Setup
Thinking in components
CommentBox
CommentList
Comment
Comment
CommentForm
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
);
}
});
React.render(
<CommentBox />,
document.getElementById('content')
);
Component
JSX is a JavaScript syntax extension that looks similar to XML.
You can use a simple JSX syntactic transform with React.
var CommentList = React.createClass({
render: function() {
return (
<div className="commentList">
Hello, world! I am a CommentList.
</div>
);
}
});
var CommentForm = React.createClass({
render: function() {
return (
<div className="commentForm">
Hello, world! I am a CommentForm.
</div>
);
}
});
Composing components
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList />
<CommentForm />
</div>
);
}
});
Composing components
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
{this.props.children}
</div>
);
}
});
Props
var CommentList = React.createClass({
render: function() {
return (
<div className="commentList">
<Comment author="Pete Hunt">This is one comment</Comment>
<Comment author="Jordan Walke">This is *another* comment</Comment>
</div>
);
}
});
Props
var CommentList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function (comment) {
return (
<Comment author={comment.author}>
{comment.text}
</Comment>
);
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
});
Props
Props
- Components configuration, options if you may
- Received from parent component, and immutable
- Components are responsible for putting together the props of its child components
var CommentBox = React.createClass({
getInitialState: function() {
return {data: []};
},
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm />
</div>
);
}
});
State
var CommentBox = React.createClass({
getInitialState: function() {
return {data: []};
},
loadCommentsFromServer: function() {
// Fetch data here
this.setState({data: data});
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm />
</div>
);
}
});
State
Thinking in components
CommentBox
CommentList
Comment
Comment
CommentForm
var CommentBox = React.createClass({
getInitialState: function() {
return {data: []};
},
loadCommentsFromServer: function() {
// Fetch data here
this.setState({data: data});
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
handleCommentSubmit: function(comment) {
// submit to the server and refresh the list
this.setState({data: data});
},
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
});
Callbacks as props
var CommentForm = React.createClass({
handleSubmit: function(e) {
this.props.onCommentSubmit({author: author, text: text});
return;
},
render: function() {
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="Your name" ref="author" />
<input type="text" placeholder="Say something..." ref="text" />
<input type="submit" value="Post" />
</form>
);
}
});
Callbacks as props
State
- State starts with a default value when a componenent mounts
- Suffers from mutations in time
- Has no business fiddling with the state of its children
- You could say the state is private
Some thoughts
- New paradigm
- Everyone in the team must be confortable
- Difficult to integrate in an existing project
- Spend all the necessary time designing the components
Useful links
- https://www.youtube.com/watch?v=x7cQ3mrcKaY
- https://youtu.be/KVZ-P-ZI6W4
- https://facebook.github.io/react/docs/tutorial.html
- https://facebook.github.io/react/docs/thinking-in-react.html
- https://github.com/uberVU/react-guide/blob/master/props-vs-state.md