Morning:
Afternoon:
create-react-app
A basic React application requires a minimum of four things:
A minimal example:
<-- index.html -->
<html>
<head>
<title>Basic React App</title>
<script src="App.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
// App.js
class App extends React.Component {
render() {
return (
<h1>Hello, world!</h1>
)
}
}
ReactDOM.render(<App />, document.querySelector('#app'))
The body of the HTML above contains only an empty div
with an id of ‘app’. This is where we will tell React to render our app. The App.js
file defines the App
component, and also makes the call to ReactDOM.render
, which attaches <App />
to the div#app
element.
React will ‘fill in’ the div with the return result of the App
component’s render
method, in this case, the markup <h1>Hello, world!</h1>
.
React components can be thought of as JavaScript functions. They take in arguments, called props
, and return markup that gets rendered to the page. Props can be just about anything, including strings, booleans, functions, objects, etc…
class App extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}!</h1>
)
}
}
<App name="Bob" />
By passing in the string "Bob"
to the App
component, we can access that value from within the App
class as a property on this.props
.
Our rendered output would then be:
<h1>Hello, Bob!</h1>
Components receive props as arguments and cannot change their values. Data that needs to change belongs in state.
State should be initialized in the constructor and updated via setState
.
Always use setState
to modify a component’s state. The only time you should set state directly is in the constructor.
class App extends React.Component {
constructor() {
super()
this.state = {
count: 0
}
}
increment(ev) {
count = this.state.count + 1
this.setState({ count })
}
render() {
return (
<button type="button" onClick={this.increment.bind(this)}>
Click to Increment
</button>
<p>
Button has been clicked {this.state.count} times
<p>
)
}
}
<App />
With modules, you can define each component in separate files, importing them as needed.
Header.js
class Header extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}!</h1>
)
}
}
export default Header
App.js
import Header from './Header'
class App extends React.Component {
render() {
return (
<Header name="Bob" />
)
}
}
export default App
create-react-app
Not every React Component needs to have state. Many simply render a bit of props
and UI. For such components, we don’t need to instantiate a whole class that inherits from React.Component
, we can simply write a function that accepts props
as an argument and returns the markup we need.
For instance, in the previous example, the Person
component can easily be re-written as a Stateless Functional Component.
function Person (props) {
return (
<li>Hello, {props.person.name}!</li>
)
}
// Or...
const Person = (props) => <li>Hello, {props.person.name}!</li>
Property initializers are a Stage 3 proposal for ECMAScript, meaning that they’re a candidate, but requires further refinement and feedback from implementations and users before it becomes part of the standard. Facebook itself is already using these techniques in production, however.
From the proposal:
“Class instance fields” describe properties intended to exist on instances of a class (and may optionally include initializer expressions for said properties).
We can take advantage of this in React.
Read more: Using ES7 property initializers in React
We can use a property initializer to set the initial value of state without writing a constructor:
class Song extends React.Component {
state = {
versesRemaining: 5,
}
}
We can even set default props and use those in the initial state:
class Song extends React.Component {
static defaultProps = {
autoPlay: false,
verseCount: 10,
}
state = {
versesRemaining: this.props.verseCount,
}
}
Combining property initializers and arrow functions gives us a convenient way to auto-bind this
, since arrow functions inherit this
from the scope in which they are declared (lexical scoping):
class Something extends React.Component {
handleButtonClick = (ev) => {
// `this` is bound correctly!
this.setState({ buttonWasClicked: true });
}
}
map
and passing in the props they need