Notes in WIP
Components are created by calling createClass
on the React
object
render()
method includes the markup to draw the component on the page
Example:
var ButtonApp = React.createClass({
render: function(){
return (
<input type="submit" />
);
}
});
Or
class CommentBox extends React.Component {
...
}
Javascript Syntax Extension
What it does: write JS with XML-like tags
Include the child component
e.g.
App
|
|_ ButtonForm
<ButtonForm/>
Using createClass
var ButtonForm = React.createClass({
render: function(){
return (
<!-- html ... -->
);
}
});
Include the <ButtonForm/>
component:
var App = React.createClass({
render: function(){
return (
<!-- html ... -->
<ButtonForm />
);
}
});
Render the App component using React.render
React.render(<App />, document.getElementById("content"));
state
- internal to the app
props
- external and get passed around (not controlled by the component)
Props are immutable
{`${this.props.author}'s picture`}
In:
class Comment extends React.Component {
render() {
return(
<div className="comment">
<img src={this.props.avatarUrl} alt={`${this.props.author}'s picture`} />
...
</div>
);
}
}
Example:
var BUTTONTEXT = "Click the button";
<App text={BUTTONTEXT} />
text
is theprop
{BUTTONTEXT}
is evaluated in{ }
{this.props.text}
will be how App
references text
prop
Example
var BUTTONTEXT = "Click the damn button";
var ButtonForm = React.createClass({
render: function(){
return (
<!-- html -->
<h3>{this.props.text}</h3>
);
}
});
var App = React.createClass({
render: function(){
return (
<!-- html -->
<ButtonForm text={this.props.text} />
);
}
});
React.render(<App text={BUTTONTEXT} />, document.getElementById("content"));
The state is stored within the component (private, cannot be accessed by child) State is mutable
- Initialising state -
getInitialState()
- Setting state -
this.setState()
Recommended to use a method - to only update the property, not entire object
this.setState(..)
Then component re-renders
Example:
class Comment extends React.Component {
constructor() {
super();
this.state = {
isAbusive: false
};
}
render() {
return (...)
}
_toggleAbuse(event) {
event.preventDefault();
}
Example
var App = React.createClass({
getInitialState: function(){
return {
active: true
}
},
handleClick: function(){
this.setState({
active: !this.state.active
});
},
render: function(){
var buttonSwitch = this.state.active ? "On" : "Off";
return (
<input type="submit" onClick={this.handleClick} />
<p>{buttonSwitch}</p>
);
}
});
React.render(<App />, document.getElementById("content"));
Data flows from parent to child
- Minimise stateful components
- Components further down hierarchy should be passed
props
Stateful components are usually higher level, while the stateless are lower level.
When child needs to change state in the parent
Button:
The button calls the App's onUserClick
function to change state
var ButtonForm = React.createClass({
render: function(){
return (
<div>
<input type="submit" onClick={this.props.onUserClick} />
<h3>You have pressed the button {this.props.counter} times!</h3>
</div>
);
}
});
App
var App = React.createClass({
getInitialState: function(){
return {
counter: 0
}
},
onUserClick: function(){
var newCount = this.state.counter + 1;
this.setState({
counter: newCount
});
},
render: function(){
return (
<div>
<h1> Welcome to the counter app!</h1>
<ButtonForm counter={this.state.counter} onUserClick={this.onUserClick} />
</div>
);
}
});
Changing the DOM directly
(Not updating the component or accessing state/props)
React.findDOMNode(component)
Example
<input ref="textField" ... />
To access
this.refs.textField
var ButtonForm = React.createClass({
focusOnField: function(){
React.findDOMNode(this.refs.textField).focus();
},
render: function(){
return (
<input type="submit"
value="Focus on the input!"
onClick={this.focusOnField} />
);
}
});
...
});
var App = React.createClass({
render: function() {
return
<ButtonForm />
...
}
)};
React.render(<App />, document.getElementById("content"));
When: Creating components dynamically
Example
todos
- List of strings, stored in App'sstate
- Traverse through the list and construct as
<li>
elements - On render - display
<li>
elements in<ul>
var App = React.createClass({
getInitialState: function(){
return {
todos: ["get food","drive home","eat food", "sleep"]
}
},
render: function(){
var todos = this.state.todos.map(function(todo,index){
return <li key={index}>{todo}</li>
});
return (
<div>
<h1> Welcome to the ToDo list!</h1>
<ul>
{todos}
</ul>
</div>
);
}
});
INDIRECT
event -> update state object (by user code) -> DOM updates (by React)
Set initial state in the constructor
- call
super()
first - then set initial state
this.state
class CommentBox extends React.Component {
constructor() {
super();
this.state = {
showComments: false
};
}
render() {
...
}
...
}
Example 1:
//inside render() of react component
<button onClick={this._handleClick().bind(this)}>click</button>
// method in the react component
_handleClick() {
this.preventDefault();
this.setState({
showComments: !this.state.showComments
});
}
Example 2:
<form onSubmit={this._handleSubmit.bind(this)}> ... </form>
_handleSubmit(event) {
event.preventDefault();
}
Example 1:
In render()
of react component
<input placeholder="Name:" ref={(input) => this._author = input} />
Example 2:
On render()
on the react component
<textarea
placeholder="Comment:"
ref={textarea => this._body = textarea}
onKeyUp={this._getCharacterCount().bind(this)}
></textarea>
As a method in the react component
_getCharacterCount() {
this.setState({characters: this._body.value.length});
}