Morning:
Afternoon:
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"
/>
)
}
}
react-contenteditable
packageThis package provides a React component for a div with editable contents, handling all the messy stuff (like dangerouslySetInnerHTML
).
import React from 'react'
import ContentEditable from 'react-contenteditable'
class MyComponent extends React.Component {
constructor() {
this.state = {
html: "<strong>Hello, <em>World</em>!</strong>"
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(ev) {
this.setState({ html: evt.target.value })
}
render() {
return (
<ContentEditable
html={this.state.html} // innerHTML of the editable div
disabled={false} // use true to disable
onChange={this.handleChange} // handle innerHTML change
/>
)
}
}
Yesterday, we used property initializers to set a component’s initial state without adding a constructor. Combining property initializers and arrow functions also gives us a convenient way to auto-bind this
:
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 Thing List, 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 --save 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
For your Firebase database, you can set up rules (written in JSON) that specify the conditions under which data is allowed to be read or written. By default, a newly generated project will require that a user be authenticated to read or write any data.
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
If you do not have authentication set up yet, these values can be set to true
. This allows anyone to read or write any data in the database. This can be convenient, but probably not a good idea long-term (and you will get a warning if you do that).
Additional rules can be applied per endpoint:
{
"rules": {
"emails": {
".read": true,
".write": "auth != null"
},
"texts": {
".read": true,
".write": "auth != null"
},
"users": {
"$userId": {
".read": "auth != null && auth.uid == $userId",
".write": "auth != null && auth.uid == $userId"
}
}
}
}
The above rules translate to:
uid
matches the $userId
of that itemHint: HTML 5 includes an input type date, i.e. <input type="date" />