Reading and Writing from a Database with React (simplified)
Tags: react, database, fullstack, beginners
Published: 2021-01-15 15:31:08

The ability to make read and write commands from a database is one of the most standard, necessary skill for any backend developer. So naturally, when I began to venture into the world of building [dynamic websites](https://dev.to/singhshemona/learning-nodejs-part-2-server-side-and-dynamic-sites-4a0h) it was one of the first requirements that came up. When I attempt to picture logistically the flow of what reading and writing from a database must be, it feels simple. My only hope is that it's as simple in practice. 

It is.

Well, I should clarify - I'm using Firebase. Why? It has one of the more generous free plans amongst the database land, and as a tinkerer who is never quite sure what restrictions some of the spaces I'm working in have, it made sense that I choose Firebase. I went through several awesome tutorials (two of my favorites linked at the bottom of this post), and many of which had some step that either did not work for me or were missing some vital feature. This tutorial is going to be the most barebones version of my collection of steps that ended up working. 

Any frustrations I had from the wonderful tutorials performing similar tasks stemmed from not being embarrassingly simple to do. Most of them had an end-UI goal in mind, which the building out of added fluff to the parts of the tutorial I was really trying to get at. **Therefore in this post, we're not building anything. We are simply learning to send some data to a database and then retrieve that data.**

### 1 - Set up your account
If you go to the [Firebase console](https://console.firebase.google.com/) and you don't see an option to add a project:

![Option to add project](https://dev-to-uploads.s3.amazonaws.com/i/ltegevkvn815opuhu8v0.png)

Then that means you aren't yet set up with an account. Pretty hard to go on without doing this part. So, let's get you an account. 
1. [Sign up with an existing Google account](https://console.firebase.google.com/)
2. Now you should be led to your console. Click the "Add project" button (from the above image) and follow through with the default settings it provides.

### 2 - Save your configuration details
In order for you to talk to your database, you need to get some special configuration details that the database can then authorize your attempted connection with. On approval of these details, the database can then spill the details you request. 
1. Click on the project you just made. You should be seeing a dashboard of sorts that provides all kinds of insights. On the left, you'll see a menu. Under 'Build', click on 'Realtime Database'. 
2. When you scroll down, you'll see a white box that says 'There are no apps in your project'. Click on the `</>`.
3. Name the app what you'd like. Leave the hosting option unchecked and click on 'Register app'. Follow the default prompts. 
4. You're going to get some HTML with a variable called 'firebaseConfig'. These are your config details. In your code editor of choice, open your project (or create a new React project to follow along with this tutorial) and create a file called `config.js` (or whatever you'd like to name your config details). Paste the following into that file:

```javascript
import Firebase from 'firebase';

const config = {
  apiKey: '',
  authDomain: '',
  databaseURL: '',
  projectId: '',
  storageBucket: '',
  messagingSenderId: '',
  appId: '',
  measurementId: '',
};

const app = Firebase.initializeApp(config);
const db = app.database();
export default db;
```

5. Go back to that HTML that Firebase gave you. If you can't find it, it's in your project settings. Fill out the empty strings in the `config` object you just made with the corresponding details from the `firebaseConfig` object.

### 3 - Make a call to the database
Now that you have what you need to be authorized, you can set up a connection to your database so it knows you want to be heard. But, you need a package to help you do this. So first install the firebase package with the following command: `npm install firebase`.

### 4 - Now I want to...send some data
Since our database is empty, it makes sense that we first want to put something into it. Firebase works with json files, so you can just make a json file containing the data you'd like and upload it to your database with the 'import json' button. You can find this button by clicking on 'Realtime Database' on the left menu and selecting the 3 vertical dots on the top right of your database.

But, that's no fun. Also, it's not how you would work with a database in actuality. So, let's pretend some event just occurred and we want to let Firebase know to store a piece of information resulting from it. I've outlined below how this would be done. To make sense of it, follow the code in the order of the steps provided: 

```typescript
import React, { useState } from 'react'
// 1 - Import your db config
import { db } from '/config.js'

// 2 - Let's start building our component, we're giving it
// the name SendData
export const SendData = () => {
// 3 - We'll set up two states, the values of which will 
// be sent to the database
  const [ text, setText ] = useState('');
  const [ num, setNum ] = useState(0);

// 5 - This is where the magic happens. When the 'Send to
// Database' button is clicked, we tell the database we 
// imported in step #1 as db to push to its root (/) whatever 
// values we have in our 'text' and 'num' states. You might be 
// wondering what 'number' and 'words' are - they are the 
// names of the keys that will be paired with the values from 
// our state. You can change them to what you'd like  
  const send = () => {
    db.ref('/').push({ 
      number: num,
      words: text,
     });
  }

  return (
// 4 - A simple form (yes I know it's not accessible, bare 
// with me) that will store the value of the number and any 
// words you input into the states we setup in step #3. The 
// button runs the 'send' function (see step #5) when it's clicked
    <form>
      <input type="number" onChange={getNum => setNum(getNum)} placeholder='Enter a number' />
      <input type="text" value={text} onChange={getText => setText(getText)} placeholder='Enter some text' />
      <button onClick={send}>
        Send to Database
      </button>
    </form>
  );
}
```

Try playing around with this component, sending different keys and values. Maybe make different state types altogether.

Assuming you followed steps #1-4 with success, upon clicking that 'Send to Database' button the data you enter will now show up in your Firebase console under 'Realtime Database'. Try entering and submitting more values and see how your database fills up! If you don't see anything, be sure to refresh the Firebase page.

### 5 - Now I want to....get some data
Now we have a filled database - yay! How about if we wanted to see all the values in this database? Let's add another component that does just that. This time, we'll use the `useEffect` hook to establish a connection to the database once the component mounts, and let Firebase know what we want within there:

```typescript
// 1 - Import the usual statements 
import React, { useState, useEffect } from 'react';
import { db } from '../../config.js';

// 2 - Now we're building a component that gets the data, so 
// we'll call it GetData
export const GetData = () => {
// 3 - Set up a state that will hold the data we receive from 
// the database in useEffect(). This will make it easy for us 
// to just read from this state. It's going to give us back an 
// object, so we'll initialize the state as an empty object 
  const [ data, setData ] = useState({});

// 4 - Here, we're saying at the root (/) of the database, get 
// a snapshot of all the values you see. Set the result of
// this attempt into a variable named 'info'. Since 'info' is 
// an object, we'll use the spread operator to pass all of 
// it's values to a variable called 'allInfo', and then update 
// our state to be the value of 'allInfo'
  useEffect(() => {
    db.ref('/').on('value', (querySnapShot:any) => {
      let info = querySnapShot.val() ? querySnapShot.val() : {};
      let allInfo = {...info};
      setData(allInfo)
    });
  }, [])

  return (
// 5 - We potentially have something inside of our 'data' 
// state. I say 'potentially', because something could go 
// wrong and we might not be able to read from the database. 
// If this happens, our 'data' state will be empty. So, let's 
// use a [conditional operator](https://reactjs.org/docs/conditional-rendering.html#inline-if-else-with-conditional-operator) to first test if it's empty and give our reader a message. 
      {data === {} ? "no data to show here!" :
// 6 - Now for the 'assuming we have some data' part. Since 
// it's an object, we can use the following syntax to parse 
// through it (much like we can loop through an array with 
// map()) and spit out each value of the keys we set earlier 
// in step #4, 'number' and 'words'.
        {Object.values(data).map((value) => 
          <ul>
            <li>{value.number}</li>
            <li>{value.words}</li>
          </ul>
      )}
    }
  );
}
```

This code will render on the page a list of all of the 'numbers' along with their 'words' that you submitted through the form in step #4. If you skipped step #4 and just uploaded a json file, then it will still work - just be sure that you change 'number' and 'words' to be whatever keys you set in your database.

There are many tiny details throughout this setup that can go haywire, such as the specific values you use in your database, getting your configuration correct, TypeScript-specific issues and much more. It's the reason why I wasn't able to follow just one tutorial. Thus, I've tried many variations of making a simple read and write system and finally boiled it down to the above code. I'm hoping this tutorial helps drown out the noise by filtering down to the absolute basics what it takes to interact with a Firebase database.

If you have specific problems that come up while going through this tutorial, feel free to message me and I'd be happy to help debug. I've probably come across it as well. 😅

---

Thank you to the following posts that were a part of the journey in making sense of working with Firebase. There were several more, but these brought me the furthest along:

1. [Build a React & Firebase Blog Site](https://ashleemboyer.com/react-firebase-blog-01)
2. [Storing and retrieving data for React Native apps with Firebase](https://blog.logrocket.com/storing-retrieving-data-react-native-apps-firebase/)

Thanks to [Lynda.com](https://www.lynda.com/SQL-Server-tutorials/Database-Fundamentals-Administration/385695-2.html) for the cover photo.