Begin React Workshop
the plan
- concepts & practise
- extras
- build a thing
the hope
- understand concepts
- know how to think
- know how to build
starting out
git clone https://github.com/foundersandcoders/begin_react_workshop.git
cd begin_react_workshop
npm install
git checkout babysteps
mkdir -p build/js
npm run dev
package.json
"scripts": {
"dev": "npm run serve & npm run live-reload & npm run build:watch",
"prebuild": "npm run lint",
"build": "browserify -t reactify --es6 src/js/main.jsx -o build/js/main.js",
"build:watch": "watchify src/js/main.jsx -t reactify --es6 -o build/js/main.js",
"lint": "jsxhint src/**/*.jsx",
"live-reload": "live-reload build/ --port 9081",
"serve": "http-server -s"
}
branches
- master references & resources
- babysteps our journey begins
- babystepsA a little helping code
- kidsteps more fundamentals
- appmockup plan for the app
- appcomplete a working version
my first render
var React = require("react");
React.render(
<div>hi</div>,
document.getElementById("content")
);
ugh
// JSX
React.render(
<div>hi</div>,
document.getElementById("content")
);
// plain js
React.render(
React.createElement("div", null, "hi"),
document.getElementById("content")
);
components
- building blocks of ui
- logically distinct
- most fundamental part of react
- power lies in composition
components
var React = require("react");
var UserName = React.createClass({
render: function() {
var name = "anon";
return (
<div>
<h1>{name}</h1>
</div>
);
}
});
React.render(<UserName />, document.getElementById("content"));
props
- one of two ways to customise components
- external circumstances
- immutable parameters
- passed like attributes
props 1
var React = require("react");
var UserName = React.createClass({
render: function() {
return (
<h1>{this.props.name}</h1>
);
}
});
var UserStatus = React.createClass({
render: function() {
return (
<p>{this.props.content}</p>
);
}
});
props 2
var LikeButton = React.createClass({
getDefaultProps: function() {
return {
liked: false
};
},
render: function() {
var buttonClass = "like";
if(this.props.liked) {
buttonClass += " yup";
}
return (
<button className={buttonClass}>
S
</button>
);
}
});
props 3
var User = React.createClass({
render: function() {
return (
<div className="app">
<UserName name="anon" />
<LikeButton liked={true} />
<UserStatus content="something about the election" />
</div>
);
}
});
React.render(<User />, document.getElementById("content"));
other stuff
- getDefaultProps()
- Components can be used in render()
- one root node - nest other components
- self-closing JSX
- className rather than class
- subtracting "yup"?
state
- the other way to customise components
- internal & private
- dynamic
- setState() merges & triggers re-render
- getInitialState()
state
var LikeButton = React.createClass({
getInitialState: function() {
return {
liked: false
};
},
clickHandler: function(e) {
this.setState({
liked: !this.state.liked
});
},
render: function() {
var buttonClass = "like";
if(this.state.liked) {
buttonClass += " yup";
}
return (
<button className={buttonClass} onClick={this.clickHandler}>
{this.state.liked ? "-" : "+"}
</button>
);
}
});
event handlers
- inline in JSX
- event delegation
- single top-level listener
- e
- camelCase
- partial application
onClick={this.clickHandler.bind(null, "first argument")}
higher level state
- common parent
- functions as props
state v2.1
var React = require("react");
var UserName = React.createClass({
render: function() {
return (
<h1>{this.props.name}</h1>
);
}
});
var UserStatus = React.createClass({
render: function() {
return (
<p>{this.props.content + (this.props.liked ? " :)" : " :(")}</p>
);
}
});
state v2.2
var LikeButton = React.createClass({
clickHandler: function(e) {
this.props.toggleLike();
},
render: function() {
var buttonClass = "like";
if(this.props.liked) {
buttonClass += " yup";
}
return (
<button className={buttonClass} onClick={this.clickHandler}>
{this.props.liked ? "-" : "+"}
</button>
);
}
});
state v2.3
var User = React.createClass({
getInitialState: function() {
return {
liked: false
};
},
toggleLike: function() {
this.setState({
liked: !this.state.liked
});
},
render: function() {
return (
<div className="app">
<UserName name="anon" />
<LikeButton liked={this.state.liked} toggleLike={this.toggleLike} />
<UserStatus liked={this.state.liked} content="something about the election" />
</div>
);
}
});
React.render(<User />, document.getElementById("content"));
dynamic kids
- arrays of components
- keys keys keys!
dynamic kids
var ListItem = React.createClass({
render: function() {
return <li>{this.props.content}</li>;
}
});
var ListHolder = React.createClass({
getInitialState: function() {
return {
arrayOfData: ["hi", "how", "are", "you"]
}
},
render: function() {
var arrayOfComponents = this.state.arrayOfData.map(function(e,i) {
return (
<ListItem key={i} content={e} />
);
});
return (
<ul>
{arrayOfComponents}
</ul>
);
}
});
refs
- like ids for components
- React.findDOMNode()
refs
var React = require("react");
var RefExample = React.createClass({
componentDidMount: function() {
console.log(this.refs.someOtherRef);
console.log(React.findDOMNode(this.refs.textinput).value);
},
render: function() {
return (
<div>
<SomeOtherComponent ref="someOtherRef" />
<input type="text" value="hello" ref="textinput" />
</div>
);
}
});
React.render(
<RefExample />,
document.getElementById("content")
);
forms
- uncontrolled?
- controlled?
uncontrolled
var uncontrolledFormComponent = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var textInputValue = React.findDOMNode(this.refs.textInput).value;
doSomethingElse(textInputValue);
},
render: function() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" defaultValue="Hello!" ref="textInput" />
<input type="button" onSubmit={this.handleSubmit}/>
</form>
);
}
});
controlled
var controlledFormComponent = React.createClass({
getInitialState: function() {
return {value: "Hello friends"};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
var value = this.state.value;
return <input type="text" value={value} onChange={this.handleChange} />;
}
});
PropTypes
- validation
- debugging
- ease-of-reading
- disabled in production
validation - proptypes
var Props = React.PropTypes
React.createClass({
propTypes: {
optionalArray: Props.array,
optionalEnum: Props.oneOf(['News', 'Photos']),
optionalArrayOf: Props.arrayOf(Props.number),
optionalObjectWithShape: Props.shape({
color: Props.string,
fontSize: Props.number
}),
requiredFunc: Props.func.isRequired
});
Begin React Workshop
By James Griffiths
Begin React Workshop
- 1,034