Skip to content

Commit 3f9f766

Browse files
committedOct 7, 2019
[step-060] add firebase configuration, save responses directly to firestore
1 parent 463d309 commit 3f9f766

File tree

8 files changed

+55
-71
lines changed

8 files changed

+55
-71
lines changed
 

‎.env.example

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
REACT_APP_FIREBASE_API_KEY=
2+
REACT_APP_FIREBASE_AUTH_DOMAIN=
3+
REACT_APP_FIREBASE_DATABASE_URL=
4+
REACT_APP_FIREBASE_PROJECT_ID=
5+
REACT_APP_FIREBASE_STORAGE_BUCKET=
6+
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=
7+
REACT_APP_FIREBASE_APP_ID=

‎README.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@ This is the companion repository to [React, Firebase & Bacon](https://frontarm.c
66
Each branch within this repository contains code for one or more steps within the course. [See an outline and installation instructions at the master branch »](https://github.com/frontarm/react-firebase-bacon)
77

88

9-
Step 055 - Programmatic navigation
9+
Step 060 - Firestore configuration
1010
--------
1111

1212
This step makes the following changes:
1313

14-
- Splits the thankyou screen out into a separate route at `/thanks`.
15-
- Programmatically navigates to `/thanks` when a submit completes successfully.
14+
- Add the [firebase](https://npmjs.com/package/firebase) package as a dependency.
15+
- Add a `firestore.rules` file that (mostly) locks down the firestore database, and tell Firebase to use it in `firebase.json`.
16+
- Add `src/config.js`, which exports an object with the app's config, as set by your environment variables at build time.
17+
- Add an `.env.example` file (you can rename this `.env.local` and add your Firebase configuration, to set your environment variables for config.js).
18+
- Replace `src/backend.js` with code to initialize firestore.
19+
- Remove code to display a response count from the Landing route, and replace the call to the `postResponse` function with a direct call to Firestore.
1620

1721
Related lessons:
1822

‎firebase.json

+3
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@
1212
"destination": "/index.html"
1313
}
1414
]
15+
},
16+
"firestore": {
17+
"rules": "firestore.rules"
1518
}
1619
}

‎firestore.rules

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
service cloud.firestore {
2+
match /databases/{database}/documents {
3+
// Keep everything locked down by default
4+
match /{document=**} {
5+
allow read, write: if false;
6+
}
7+
8+
match /responses/{id} {
9+
allow create;
10+
}
11+
}
12+
}

‎package.json

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6+
"firebase": "^7.1.0",
67
"history": "^4.10.1",
78
"react": "^16.10.2",
89
"react-dom": "^16.10.2",

‎src/backend.js

+5-32
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,7 @@
1-
const BaseURL =
2-
'https://us-central1-example-project-4ad97.cloudfunctions.net/api'
1+
import firebase from 'firebase/app'
2+
import 'firebase/firestore'
3+
import config from './config'
34

4-
export async function getResponseCount() {
5-
let res = await window.fetch(BaseURL + '/response-count')
6-
let { data } = await res.json()
7-
return data.count
8-
}
5+
let firebaseApp = firebase.initializeApp(config.firebase)
96

10-
/**
11-
* Submit an email address and name to a test server, and returns
12-
* the server response's body in case of success, invalid input
13-
* or a conflict with existing data.
14-
*/
15-
export async function postResponse({ email, name }) {
16-
let res = await window.fetch(BaseURL + '/response', {
17-
method: 'POST',
18-
headers: {
19-
'Content-Type': 'application/json',
20-
},
21-
body: JSON.stringify({
22-
email,
23-
name,
24-
}),
25-
})
26-
27-
// If the server returns something other than expected, throw the
28-
// response to indicate an error.
29-
if (res.status !== 200 && res.status !== 400 && res.status !== 409) {
30-
throw res
31-
}
32-
33-
return res.json()
34-
}
7+
export const db = firebaseApp.firestore()

‎src/config.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export default {
2+
firebase: {
3+
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
4+
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
5+
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
6+
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
7+
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
8+
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
9+
appId: process.env.REACT_APP_FIREBASE_APP_ID,
10+
},
11+
}

‎src/routes/landing.js

+9-36
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import React, { useEffect, useState } from 'react'
1+
import React, { useState } from 'react'
22
import { css } from 'styled-components/macro'
33

4-
import { getResponseCount, postResponse } from 'backend'
4+
import { db } from 'backend'
55
import { StyledButton } from 'components/buttons'
66
import NarrowCardLayout from 'components/narrowCardLayout'
77
import { Field } from 'components/fields'
@@ -37,35 +37,14 @@ function validate({ email, name }) {
3737
}
3838

3939
export default function Landing({ navigate }) {
40-
const [responseCount, setResponseCount] = useState(undefined)
40+
const [responseCount, setResponseCount] = useState(0)
4141
const [name, setName] = useState('')
4242
const [email, setEmail] = useState('')
4343
const [status, setStatus] = useState({
4444
type: 'fresh',
4545
})
4646
const params = { name, email }
4747

48-
useEffect(() => {
49-
let hasBeenUnmounted = false
50-
getResponseCount().then(
51-
count => {
52-
if (!hasBeenUnmounted) {
53-
setResponseCount(count || 0)
54-
}
55-
},
56-
() => {
57-
if (!hasBeenUnmounted) {
58-
// There's no need to display an error if we can't get the count.
59-
// Just set it to zero to hide the count.
60-
setResponseCount(0)
61-
}
62-
},
63-
)
64-
return () => {
65-
hasBeenUnmounted = true
66-
}
67-
}, [])
68-
6948
const handleSubmit = async event => {
7049
event.preventDefault()
7150

@@ -83,19 +62,13 @@ export default function Landing({ navigate }) {
8362
})
8463

8564
try {
86-
const result = await postResponse(params)
87-
if (result.status === 'error') {
88-
setStatus({
89-
type: 'error',
90-
issues: result.issues || {
91-
base: 'error',
92-
},
93-
params,
94-
})
95-
} else {
96-
navigate('/thanks')
97-
}
65+
await db
66+
.collection('responses')
67+
.doc()
68+
.set(params)
69+
navigate('/thanks')
9870
} catch (error) {
71+
console.error(error)
9972
setStatus({
10073
type: 'error',
10174
issues: {

0 commit comments

Comments
 (0)
Please sign in to comment.