<\/figure>\nAdding a new Potluck Item to your Database<\/h3>\n Now that we’re tracking our inputs, let’s make it so that we can add a new item to our database so that Firebase can keep track of it.<\/p>\n
First we’ll need to connect to Firebase in order to do this, we’ll start by importing our firebase<\/code> module that we created earlier. We’ll also delete the logo.svg<\/code> import, since it’s just an unneeded part of the create-react-app boiler plate and will cause warnings if we don’t:<\/p>\nimport React, { Component } from 'react';\r\nimport logo from '.\/logo.svg'; \/\/ <--- remove this line\r\nimport '.\/App.css';\r\nimport firebase from '.\/firebase.js'; \/\/ <--- add this line<\/code><\/pre>\nOnce that’s done, we’ll need to make our ‘Add Item’ button let Firebase know what we’d like to add to our database and where we’d like to put it.<\/p>\n
First we’ll attach a submit event listener for our form, and have it call a handleSubmit<\/code> method we’ll write in a minute:<\/p>\n<form onSubmit={this.handleSubmit}>\r\n <input type=\"text\" name=\"username\" placeholder=\"What's your name?\" onChange={this.handleChange} value={this.state.username} \/>\r\n <input type=\"text\" name=\"currentItem\" placeholder=\"What are you bringing ?\" onChange={this.handleChange} value={this.state.currentItem} \/>\r\n <button>Add Item<\/button>\r\n<\/form><\/code><\/pre>\nDon’t forget to bind it in the constructor!<\/p>\n
constructor() {\r\n super();\r\n this.state = {\r\n currentItem: '',\r\n username: ''\r\n }\r\n this.handleChange = this.handleChange.bind(this);\r\n this.handleSubmit = this.handleSubmit.bind(this); \/\/ <-- add this line\r\n}<\/code><\/pre>\nAnd now add the handleSubmit<\/code> method to your component:<\/p>\nhandleSubmit(e) {\r\n e.preventDefault();\r\n const itemsRef = firebase.database().ref('items');\r\n const item = {\r\n title: this.state.currentItem,\r\n user: this.state.username\r\n }\r\n itemsRef.push(item);\r\n this.setState({\r\n currentItem: '',\r\n username: ''\r\n });\r\n}<\/code><\/pre>\nLet’s break down what’s going here:<\/p>\n
\ne.preventDefault()<\/code> – we need to prevent the default behavior of the form, which if we don’t will cause the page to refresh when you hit the submit button.<\/li>\nconst itemsRef = firebase.database().ref(<\/code>'<\/code>items<\/code>'<\/code>);<\/code> – we need to carve out a space in our Firebase database where we’d like to store all of the items that people are bringing to the potluck. We do this by calling the ref<\/code> method and passing in the destination we’d like them to be stored (items<\/code>).<\/li>\nconst item = { \/* .. *\/ }<\/code> here we grab the item the user typed in (as well as their username) from the state, and package it into an object so we ship it off to our Firebase database.<\/li>\nitemsRef.push(item)<\/code> similar to the Array.push<\/code> method, this sends a copy of our object so that it can be stored in Firebase.<\/li>\nFinally this.setState({ currentItem: '', username:<\/code> ''<\/code> });<\/code> is just so that we can clear out the inputs so that an additional item can be added.<\/li>\n<\/ul>\nNow try adding a new item, and hitting submit! If you don’t have any errors in your console, you should be able to head on over to the Firebase dashboard, where you’ll see something like this inside your Database tab:<\/p>\n <\/figure>\nIf you click the little + next to items<\/code> you’ll be able to look inside, like this:<\/p>\n <\/figure>\nThat strange looking -Kk8lHSMqC5oP6Qai0Vx<\/code> key you see is a programmatically generated key created by Firebase when we called the push<\/code> method, but inside you’ll find whatever item you added to the Potluck.<\/p>\nYou’ll notice that all of our records are stored as objects with properties that have the generated names you see above – just another quick reminder that there are no arrays in Firebase! <\/p>\n
Try adding more items and see what happens.<\/p>\n
Way to go! We’re almost there, but we still have one more step: getting our potluck items to appear on the page.<\/p>\n
Retrieving our Potluck Items from the database<\/h3>\n Just like in a traditional React app, we need to find some way to keep track of all of the potluck dishes so that we can display what people are planning to bring on to the page.<\/p>\n
Without a database, this poses an issue, since every time we refresh the page any new dishes that were added to the potluck would get lost. But with Firebase, this is a snap to fix!<\/p>\n
First, let’s create a variable called items<\/code> inside of default state. This will eventually hold all of the potluck items that are currently being tracked inside of our Firebase database.<\/p>\nconstructor() {\r\n super();\r\n this.state = {\r\n currentItem: '',\r\n username: '',\r\n items: []\r\n }\r\n this.handleChange = this.handleChange.bind(this);\r\n this.handleSubmit = this.handleSubmit.bind(this);\r\n}<\/code><\/pre>\nNext, we need to actually grab those items from our Firebase database so that we can store them into our state.<\/p>\n
The Firebase API offers us an incredibly easy way to not only grab this kind information from our database, but also to update us when new values get added to our database. It accomplishes this using the value<\/code> custom event listener. <\/p>\nIt looks like this:<\/p>\n
itemsRef.on('value', (snapshot) => {\r\n console.log(snapshot.val());\r\n});<\/code><\/pre>\nThe callback here, which we’ve called snapshot<\/code>, provides you with a bird’s eye overview of the items<\/code> ref inside of your database. From here, you can easily grab a list of all of the properties inside of that items<\/code> ref, using the .val()<\/code> method which you can call on the snapshot.<\/p>\nThis value automatically fires on two occassions:<\/p>\n
\nAny time a new item is added or removed from our items<\/code> reference inside of our database<\/li>\nThe first time the event listener is attached<\/li>\n<\/ol>\nThis makes it especially useful for initially grabbing a list of all of the items inside of our database, and then subsequently tracking when new items get added and removed.<\/p>\n
We’ll attach this event listener inside of our componentDidMount<\/code>, so that we start tracking our Potluck items as soon as our component loads on to the page:<\/p>\ncomponentDidMount() {\r\n const itemsRef = firebase.database().ref('items');\r\n itemsRef.on('value', (snapshot) => {\r\n let items = snapshot.val();\r\n let newState = [];\r\n for (let item in items) {\r\n newState.push({\r\n id: item,\r\n title: items[item].title,\r\n user: items[item].user\r\n });\r\n }\r\n this.setState({\r\n items: newState\r\n });\r\n });\r\n}<\/code><\/pre>\nHere, we instantiate a new array and populate it with the results that come back from our value<\/code> listener. We for\u2026in<\/code> over each key, and push the result into an object inside our newState<\/code> array. Finally, once all the keys are iterated over (and therefore all items are grabbed from our database), we update the state with this list of items from our database.<\/p>\nInspect your App using the React Dev Tools – you’ll notice that you now have an items<\/code> property inside of your state with all of the items people have submitted for your potluck!<\/p>\nDisplaying Potluck Items on the Page<\/h3>\n Now let’s get these potluck items to actually display on the page. This is relatively easy, now that we have a list of all of our items being grabbed from Firebase and stored inside of our state. We just map over it and print the results on to the page, like so:<\/p>\n
<section className='display-item'>\r\n <div className=\"wrapper\">\r\n <ul>\r\n {this.state.items.map((item) => {\r\n return (\r\n <li key={item.id}>\r\n <h3>{item.title}<\/h3>\r\n <p>brought by: {item.user}<\/strong><\/p>\r\n <\/li>\r\n )\r\n })}\r\n <\/ul>\r\n <\/div>\r\n<\/section><\/code><\/pre>\nTry adding a new item through your form. You’ll notice that it automatically causes a new list item to appear on the page! <\/p>\n
It’s not magic, Firebase’s value<\/code> event is firing when you push<\/code> the new item into your database, and sending back a new snapshot<\/code> with a list of all of the items currently in your database, which ultimate updates your component through a setState<\/code> which triggers a re-render and displays the new item on the page. <\/p>\nBut we digress. There’s still one more step! We need to make it so that we can remove an item from the page.<\/p>\n
Removing Items from the Page<\/h3>\n We’ll need to create a new method on our component for this: removeItem<\/code>. This method will need to be passed that unique key which serves as the identifier for each one of the items inside of our Firebase database.<\/p>\nIt’s very simple, and looks like this:<\/p>\n
removeItem(itemId) {\r\n const itemRef = firebase.database().ref(`\/items\/${itemId}`);\r\n itemRef.remove();\r\n}<\/code><\/pre>\nHere, instead of grabbing all of the items as we did before when adding a new item, we instead look up a specific item by its key (that strange –Kk8lHSMqC5oP6Qai0Vx<\/code> key from before). We can then call firebase.database()<\/code>‘s remove method, which strips it from the page.<\/p>\nFinally, we’ll need to add a button to our UI with an onClick<\/code> that calls our removeItem<\/code> method and passes it the item’s key, like follows:<\/p>\n{this.state.items.map((item) => {\r\n return (\r\n <li key={item.id}>\r\n <h3>{item.title}<\/h3>\r\n <p>brought by: {item.user}<\/strong><\/p>\r\n <button onClick={() => this.removeItem(item.id)}>Remove Item<\/button>\r\n <\/li>\r\n )\r\n })\r\n}<\/code><\/pre>\nAnd that’s all there is to it! Just like our addItem<\/code> method, our UI and component state automatically update when an item is removed from the database.<\/p>\nHere’s what our completed `App.js` should look like:<\/p>\n
import React, { Component } from 'react';\r\nimport logo from '.\/logo.svg';\r\nimport '.\/App.css';\r\nimport firebase from '.\/firebase.js';\r\n\r\nclass App extends Component {\r\n constructor() {\r\n super();\r\n this.state = {\r\n currentItem: '',\r\n username: '',\r\n items: []\r\n }\r\n this.handleChange = this.handleChange.bind(this);\r\n this.handleSubmit = this.handleSubmit.bind(this);\r\n }\r\n handleChange(e) {\r\n this.setState({\r\n [e.target.name]: e.target.value\r\n });\r\n }\r\n handleSubmit(e) {\r\n e.preventDefault();\r\n const itemsRef = firebase.database().ref('items');\r\n const item = {\r\n title: this.state.currentItem,\r\n user: this.state.username\r\n }\r\n itemsRef.push(item);\r\n this.setState({\r\n currentItem: '',\r\n username: ''\r\n });\r\n }\r\n componentDidMount() {\r\n const itemsRef = firebase.database().ref('items');\r\n itemsRef.on('value', (snapshot) => {\r\n let items = snapshot.val();\r\n let newState = [];\r\n for (let item in items) {\r\n newState.push({\r\n id: item,\r\n title: items[item].title,\r\n user: items[item].user\r\n });\r\n }\r\n this.setState({\r\n items: newState\r\n });\r\n });\r\n }\r\n removeItem(itemId) {\r\n const itemRef = firebase.database().ref(`\/items\/${itemId}`);\r\n itemRef.remove();\r\n }\r\n render() {\r\n return (\r\n <div className='app'>\r\n <header>\r\n <div className=\"wrapper\">\r\n <h1>Fun Food Friends<\/h1>\r\n <\/i> \r\n <\/div>\r\n <\/header>\r\n <div className='container'>\r\n <section className='add-item'>\r\n <form onSubmit={this.handleSubmit}>\r\n <input type=\"text\" name=\"username\" placeholder=\"What's your name?\" onChange={this.handleChange} value={this.state.username} \/>\r\n <input type=\"text\" name=\"currentItem\" placeholder=\"What are you bringing?\" onChange={this.handleChange} value={this.state.currentItem} \/>\r\n <button>Add Item<\/button>\r\n <\/form>\r\n <\/section>\r\n <section className='display-item'>\r\n <div className=\"wrapper\">\r\n <ul>\r\n {this.state.items.map((item) => {\r\n return (\r\n <li key={item.id}>\r\n <h3>{item.title}<\/h3>\r\n <p>brought by: {item.user}<\/strong>\r\n <button onClick={() => this.removeItem(item.id)}>Remove Item<\/button>\r\n <\/p>\r\n <\/li>\r\n )\r\n })}\r\n <\/ul>\r\n <\/div>\r\n <\/section>\r\n <\/div>\r\n <\/div>\r\n );\r\n }\r\n}\r\nexport default App;<\/code><\/pre>\nConclusion<\/h3>\n Now you can truly see how Firebase and React play beautifully together. Firebase’s ability to persist data on the fly, coupled with React’s component life cycle, makes for an incredibly simple and powerful way to quickly build up simple applications.<\/p>\n
This article just scratches the surface of what the Firebase API can provide us. For example, with just a few more steps (and perhaps we will go over this in a future article), it would be incredibly easy to expand this application so that users could log in and out, be able to have a display photo next to the item that they are bringing, and only be able to remove their own items. <\/p>\n
Happy Firebasing!<\/p>\n