Morning: Day 7, part 1
Afternoon: Day 7, part 1
Sometimes one component needs to update another component’s state. It can’t do that directly, but it can call a method from that other component if it’s available via a prop.
Try this example live on CodePen
import React from 'react'
import ReactDOM from 'react-dom'
const PartyButton = ({ celebrate, celebrations }) => {
return <button onClick={celebrate}>Party! {celebrations}</button>
}
class App extends React.Component {
constructor() {
super()
this.state = {
celebrations: 0,
}
this.celebrate = this.celebrate.bind(this)
}
celebrate() {
const celebrations = this.state.celebrations + 1
this.setState({ celebrations })
}
render() {
return <PartyButton celebrate={this.celebrate} celebrations={this.state.celebrations} />
}
}
ReactDOM.render(<App />, document.querySelector('main'))
componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here.
import React, { Component } from 'react'
class MyComponent extends Component {
componentDidMount() {
this.nameInput.focus()
}
render() {
return (
<input
ref={(input) => { this.nameInput = input; }}
defaultValue="will focus"
/>
)
}
}
Destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
const myObj = {
a: true,
b: 'Destructuring!'
}
let { a, b } = myObj
console.log(a) // => true
console.log(b) // => 'Destructuring!'
The spread operator was added in ES6 to allow an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) or multiple variables (for destructuring assignment) are expected.
function myFunc (x, y, z) {
console.log(x)
console.log(y)
console.log(z)
}
const args = [1, 2, 3]
myFunc(...args) // the spread '...args' applies the items in args to the three arguments in myFunc
// => 1
// => 2
// => 3
It is also an easy way to make copies of iterable objects
const ary = [1, 2, 3]
const aryCopy = [...ary] // makes a copy of ary
If you are in a project using Babel (like a React project created with create-react-app), you can also use the object-rest-spread-transform to apply this same method to objects.
this.state = {'a': true, party: 'hard'}
const stateCopy = {...this.state} // makes a copy of this.state
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,
}
}
Property initializers are a Stage 2 proposal for ECMAScript, meaning that it’s still a draft and is subject to minor changes before becoming standardized. Facebook itself is already using these techniques in production, however.
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 });
}
}
Firebase is a real-time database hosted by Google. In addition to the database, it also provides features of authentication, analytics, cloud storage, and hosting. For Noteherder, we synced the state of our app to our database on Firebase. This allowed all of our data to be persisted, even after page refreshes.
Re-base is an open source package that allows easy syncing of local state with a Firebase database. Add rebase to your project with one of the following commands:
yarn add re-base # add package using yarn
npm install re-base # add package using npm
Once you have re-base installed, setup is easy! First, create a new project on Firebase, then click on “Add to a web app” to see your JavaScript config object. Next, initialize a Firebase app and database in your project using the config object, and provide the database to re-base.
import Rebase from 're-base'
import firebase from 'firebase/app'
import database from 'firebase/database'
const app = firebase.initializeApp({
apiKey: "YOURAPIKEY",
authDomain: "YOURAUTHDOMAIN",
databaseURL: "YOURDATABASEURL",
projectId: "YOURPROJECTID",
storageBucket: "YOURSTORAGEBUCKET",
messagingSenderId: "YOURSENDERID"
})
const db = database(app)
const base = Rebase.createClass(db)
export default base
Finally, call base.syncState to sync your app’s local state with Firebase. The first argument to syncState is the name of the Firebase endpoint you want to sync, and the second is a configuration object.
base.syncState('myFavoriteEndpoint', {
context: this,
state: 'items'
})
Now, any time we update the state of our app, the changes will sync with Firebase in real time.
Re-base can do much more than just syncing state. There are methods for fetch, push, post, etc. To find out more about what all you can do with re-base, check out the README