This lecture is much about why and the big ideas.
You can learn the syntax as you need it.
In particular, the thinking around breaking applications into components is probably the most important part to learn about.
There are many others, but these are among the most popular.
There are differences between them but they largely share lots of common ideas and after learning one framework, you’ll be in a better position to learn about others.
Popular, powerful front-end framework.
Developed by and sponsored by Facebook.
class Cat(object):
"""Feline catus."""
def render(self):
return "<div>...</div>"
<!DOCTYPE html>
<html>
<body>
<h1>Demo: Hello</h1>
<p>I made a React component!</p>
<div id="root"> <!-- component will go in this div --> </div>
<p>Isn't it neat?</p>
<script src="http://unpkg.com/react@15.6.2/dist/react.js"></script>
<script src="http://unpkg.com/react-dom@15.6.2/dist/react-dom.js"></script>
<script src="http://unpkg.com/babel-standalone"></script>
<script src="hello.jsx" type="text/jsx"></script>
</body>
</html>
A component is a React class
with a render method:
var Hello = React.createClass({
render: function () {
return <p>Hi World!</p>
}
});
We add our component to HTML with ReactDOM.render:
ReactDOM.render(
<Hello />,
document.getElementById("root")
);
var Hello = React.createClass({
render: function () {
return <p>Hi World!</p>
}
});
ReactDOM.render(
<Hello />,
document.getElementById("root")
);
What’s this HTML in our JavaScript?
JSX is like HTML embedded in JavaScript:
if (score > 100) {
return <b>You win!</b>
}
You can also “re-embed” JavaScript in JSX:
if (score > 100) {
return <b>You win, { playerName }</b>
}
(looks for JavaScript variable playerName)
Awesome for development — nothing to install!
Load Babel standalone library:
<script src="http://unpkg.com/babel-standalone"></script>
Mark JSX files with type="text/jsx":
<script src="hello.jsx" type="text/jsx"></script>
Read handouts to learn how to do on command line
Use Babel on Command Line
While it’s convenient to transpile JSX into JavaScript directly in the browser like this, it’s not suitable for real-world deployment: it takes a second to do the conversion, leading to a poor experience for users.
Better for deployment is to convert JSX to JavaScript once, via the command line, and then save and use the converted JS directly.
To do this:
You need to install npm
Then use npm to install Babel and settings for React:
$ npm install babel-cli babel-preset-react
To convert a file:
$ ./node_modules/.bin/babel --presets=react file.jsx > file.js
a.k.a. Props
A useful component is a reusable one.
This often means making it configurable or customizable.
var Hello = React.createClass({
render: function () {
return <p>Hi World!</p>
}
});
It would be better if we could configure our greeting.
Our greeting will be Hi ______ from ______.
Let’s make two “properties”:
var Hello = React.createClass({
render: function () {
return <p>Hi { this.props.to } from { this.props.from }</p>
}
});
Set properties on element; get using this.props.propName.
ReactDOM.render(
<Hello to="World" from="Joel"/>,
document.getElementById("root")
);
You can use a component many times:
Adding several at once:
ReactDOM.render(
<div>
<Hello to="Kay" from="Kim" />
<Hello to="me" from="you" />
</div>,
document.getElementById("root")
);
Adding to different places:
ReactDOM.render(
<Hello to="Kay" from="Kim" />,
document.getElementById("root")
);
ReactDOM.render(
<Hello to="me" from="you" />,
document.getElementById("also")
);
Properties are for configuring your component
Properties are immutable
Properties can be strings:
<User name="Jane" />
For other types, embed JS expression using the curly braces:
<User name="Jane" salary={ pay * 12 }
hobbies={ ["bridge", "Python", "tea"] } />
When you add a die, you can choose the number of sides.
Let’s make this a property.
ReactDOM.render(
<div>
<Die sides="4" />
<Die sides="6" />
<Die sides="8" />
<Die sides="10" />
<Die sides="12" />
<Die sides="20" />
</div>,
document.getElementById("root")
);
var Die = React.createClass({
getInitialState: function () {
return {result: "?"}
},
roll: function () {
var num = Math.ceil(
Math.random() * this.props.sides);
this.setState({result: num});
},
render: function () {
return (
<button className="die" onClick={ this.roll }>
<i>d{ this.props.sides }</i>
<b>{ this.state.result }</b>
</button>
);
},
});
How this works:
this.setState({...})this.state = ...Properties are set by the parent, in the JSX.
are immutable, and are for configuration.
State has an initial value, and changes over lifetime.
Changes to state trigger re-rendering of the component (and its children, if any).
Let’s examine a game built with React.
var word = randomWord();
console.log("answer = " + word);
ReactDOM.render(
<SharkWords answer={ word }/>,
document.getElementById('root'));
The random word comes from our randomWord function in words.js. This is just pure JS, unrelated to React.
var SharkWords = React.createClass({
getInitialState: function () {
return {numWrong: 0, guessed: new Set()}
},
guessedWord: function () { // "app_e" for "apple"
var word = "";
for (var ltr of this.props.answer)
word += this.state.guessed.has(ltr) ? ltr : "_";
return word;
},
handleGuess: function (evt) {
var letter = evt.target.value;
this.state.guessed.add(letter);
this.setState({guessed: this.state.guessed});
if (this.props.answer.indexOf(letter) === -1)
this.setState({'numWrong': this.state.numWrong + 1});
},
});
Ternary Operators and Sets
This snippet uses two JavaScript features you may not be familiar with. Neither are relatd to React, but they can be useful:
expression ? true-val : false-val.
This evaluates the expression and, if it evaluates to
true, returns the true-val, otherwise it returns the
false-val. These can be a handy way to compact an
if/then/else block into a single line.Set.has(val).
var SharkWords = React.createClass({
render: function () {
return (
<div className="sharkwords">
<h1>Sharkwords!</h1>
<img src={ "guess" + this.state.numWrong + ".png" }/>
<p className="guessed">
Wrong guesses: { this.state.numWrong }
</p>
<p className="word">{ this.guessedWord() }</p>
{ this.renderButtons() }
</div>
)
},
});
The rendering of the list of buttons is in a separate function just because it seemed clearer to break that out for readability; it could have been inlined here.
var SharkWords = React.createClass({
renderButtons: function () {
var buttons = [];
for (var ltr of "abcdefghijklmnopqrstuvwxyz")
buttons.push(
<button key={ ltr } value={ ltr }
disabled={ this.state.guessed.has(ltr) }
onClick={ this.handleGuess }>
{ ltr }
</button>)
return <div className="letters">{ buttons }</div>;
},
});
“Key” attribute
A small thing to note is the key attribute in
<button key={ ltr } ...>.
When React elements are made in a loop, it is very helpful for React to have a key for each. This is a unique value for each individual item, and allows React to more quickly decide which items to re-render later. Since each button has a different letter of the alphabet associated with it, we simply use that as this id-like key value.
An advanced demo of Flask and React.
Let’s take a non-codeful look at what it can teach you.
Does the homepage need Jinja?
The main app HTML goes through Jinja templating in the current app — but, really, this is overkill, since it’s completely static and uses no Jinja templating variables. This doesn’t pose a problem, but if you wanted to, you could store index.html in static/ instead of templates/, and change the route to:
@app.route("/")
def homepage():
return send_static_file("index.html")
(send_static_file is a function you import from Flask; it returns a response with the named file from the static folder)
@app.route("/")
def homepage():
return render_template("index.html")
@app.route("/melons.json")
def get_melons():
melons = [
{"type": "Watermlon", "price": randint(2, 20) / 2.0},
{"type": "Muskmelon", "price": randint(2, 5) / 2.0},
{"type": "Pupmelon", "price": randint(2, 80) / 2.0},
{"type": "Lemonmelon", "price": randint(2, 9) / 2.0}
]
return jsonify(melons=melons)
@app.route("/post-comment.json", methods=["POST"])
def post_comment():
comment = request.data
# we could save this in a database here
return jsonify(message="Saved.")
Backend-driven app
Frontend-driven app
Also in Ubermelon Site
Unrelated to React, the Ubermelon site also demonstrates some newer JS features:
jQuery
React
React
Angular2
Different Style of Making Classes
We’ve shown building components in the “classic” way:
var Hello = React.createClass({
render: function () { /* ... */ }
});
There’s also a version using syntax from ES6, the very-newest version of JavaScript:
class Hello extends React.Component {
render() { /* ... */ }
}
Tutorials and books vary on which they show.
They do the same things and you can use either. You can mix and match them in the same project.