├── assets
├── icon.png
├── favicon.png
└── splash.png
├── babel.config.js
├── .expo-shared
└── assets.json
├── .gitignore
├── app.json
├── database
└── firebase.js
├── package.json
├── App.js
└── screens
├── UsersList.js
├── CreateUserScreen.js
└── UserDetailScreen.js
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FaztWeb/expo-firebase-crud/HEAD/assets/icon.png
--------------------------------------------------------------------------------
/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FaztWeb/expo-firebase-crud/HEAD/assets/favicon.png
--------------------------------------------------------------------------------
/assets/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FaztWeb/expo-firebase-crud/HEAD/assets/splash.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(api) {
2 | api.cache(true);
3 | return {
4 | presets: ['babel-preset-expo'],
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/.expo-shared/assets.json:
--------------------------------------------------------------------------------
1 | {
2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
4 | }
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/**/*
2 | .expo/*
3 | npm-debug.*
4 | *.jks
5 | *.p8
6 | *.p12
7 | *.key
8 | *.mobileprovision
9 | *.orig.*
10 | web-build/
11 |
12 | # macOS
13 | .DS_Store
14 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "expo-firebase-crud",
4 | "slug": "expo-firebase-crud",
5 | "version": "1.0.0",
6 | "orientation": "portrait",
7 | "icon": "./assets/icon.png",
8 | "splash": {
9 | "image": "./assets/splash.png",
10 | "resizeMode": "contain",
11 | "backgroundColor": "#ffffff"
12 | },
13 | "updates": {
14 | "fallbackToCacheTimeout": 0
15 | },
16 | "assetBundlePatterns": [
17 | "**/*"
18 | ],
19 | "ios": {
20 | "supportsTablet": true
21 | },
22 | "web": {
23 | "favicon": "./assets/favicon.png"
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/database/firebase.js:
--------------------------------------------------------------------------------
1 | import firebase from "firebase";
2 | import "firebase/firestore";
3 |
4 | var firebaseConfig = {
5 | apiKey: "AIzaSyBJqKyzEvnQFKQc-y4K31zbgj9rssXHz4Y",
6 | authDomain: "react-native-97bfa.firebaseapp.com",
7 | databaseURL: "https://react-native-97bfa.firebaseio.com",
8 | projectId: "react-native-97bfa",
9 | storageBucket: "react-native-97bfa.appspot.com",
10 | messagingSenderId: "961930425654",
11 | appId: "1:961930425654:web:cdbde3f2ff278ed214ef97",
12 | };
13 |
14 | // Initialize Firebase
15 | firebase.initializeApp(firebaseConfig);
16 |
17 | const db = firebase.firestore();
18 |
19 | export default {
20 | firebase,
21 | db
22 | };
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "main": "node_modules/expo/AppEntry.js",
3 | "scripts": {
4 | "start": "expo start",
5 | "android": "expo start --android",
6 | "ios": "expo start --ios",
7 | "web": "expo start --web",
8 | "eject": "expo eject"
9 | },
10 | "dependencies": {
11 | "@react-native-community/masked-view": "0.1.10",
12 | "@react-navigation/native": "^5.8.0",
13 | "@react-navigation/stack": "^5.10.0",
14 | "expo": "~39.0.2",
15 | "expo-status-bar": "~1.0.2",
16 | "firebase": "^8.0.0",
17 | "react": "16.13.1",
18 | "react-dom": "16.13.1",
19 | "react-native": "https://github.com/expo/react-native/archive/sdk-39.0.4.tar.gz",
20 | "react-native-elements": "^3.0.0-alpha.1",
21 | "react-native-gesture-handler": "~1.7.0",
22 | "react-native-reanimated": "~1.13.0",
23 | "react-native-safe-area-context": "3.1.4",
24 | "react-native-screens": "~2.10.1",
25 | "react-native-web": "~0.13.12"
26 | },
27 | "devDependencies": {
28 | "@babel/core": "~7.9.0"
29 | },
30 | "private": true
31 | }
32 |
--------------------------------------------------------------------------------
/App.js:
--------------------------------------------------------------------------------
1 | import { StatusBar } from "expo-status-bar";
2 | import React from "react";
3 | import { StyleSheet } from "react-native";
4 |
5 | // Navigation
6 | import { NavigationContainer } from "@react-navigation/native";
7 | import { createStackNavigator } from "@react-navigation/stack";
8 |
9 | // Components
10 | import CreateUserScreen from "./screens/CreateUserScreen";
11 | import UserDetailScreen from "./screens/UserDetailScreen";
12 | import UsersList from "./screens/UsersList";
13 |
14 | const Stack = createStackNavigator();
15 |
16 | function MyStack() {
17 | return (
18 |
29 |
34 |
39 |
44 |
45 | );
46 | }
47 |
48 | export default function App() {
49 | return (
50 |
51 |
52 |
53 | );
54 | }
55 |
56 | const styles = StyleSheet.create({
57 | container: {
58 | flex: 1,
59 | backgroundColor: "#fff",
60 | alignItems: "center",
61 | justifyContent: "center",
62 | },
63 | });
64 |
--------------------------------------------------------------------------------
/screens/UsersList.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Button, StyleSheet } from "react-native";
3 | import { ListItem, Avatar } from "react-native-elements";
4 | import { ScrollView } from "react-native-gesture-handler";
5 |
6 | import firebase from "../database/firebase";
7 |
8 | const UserScreen = (props) => {
9 | const [users, setUsers] = useState([]);
10 |
11 | useEffect(() => {
12 | firebase.db.collection("users").onSnapshot((querySnapshot) => {
13 | const users = [];
14 | querySnapshot.docs.forEach((doc) => {
15 | const { name, email, phone } = doc.data();
16 | users.push({
17 | id: doc.id,
18 | name,
19 | email,
20 | phone,
21 | });
22 | });
23 | setUsers(users);
24 | });
25 | }, []);
26 |
27 | return (
28 |
29 |
60 | );
61 | };
62 |
63 | export default UserScreen;
64 |
--------------------------------------------------------------------------------
/screens/CreateUserScreen.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Button,
4 | View,
5 | StyleSheet,
6 | TextInput,
7 | ScrollView,
8 | } from "react-native";
9 |
10 | import firebase from "../database/firebase";
11 |
12 | const AddUserScreen = (props) => {
13 | const initalState = {
14 | name: "",
15 | email: "",
16 | phone: "",
17 | };
18 |
19 | const [state, setState] = useState(initalState);
20 |
21 | const handleChangeText = (value, name) => {
22 | setState({ ...state, [name]: value });
23 | };
24 |
25 | const saveNewUser = async () => {
26 | if (state.name === "") {
27 | alert("please provide a name");
28 | } else {
29 |
30 | try {
31 | await firebase.db.collection("users").add({
32 | name: state.name,
33 | email: state.email,
34 | phone: state.phone,
35 | });
36 |
37 | props.navigation.navigate("UsersList");
38 | } catch (error) {
39 | console.log(error)
40 | }
41 | }
42 | };
43 |
44 | return (
45 |
46 | {/* Name Input */}
47 |
48 | handleChangeText(value, "name")}
51 | value={state.name}
52 | />
53 |
54 |
55 | {/* Email Input */}
56 |
57 | handleChangeText(value, "email")}
62 | value={state.email}
63 | />
64 |
65 |
66 | {/* Input */}
67 |
68 | handleChangeText(value, "phone")}
71 | value={state.phone}
72 | />
73 |
74 |
75 |
76 |
78 |
79 | );
80 | };
81 |
82 | const styles = StyleSheet.create({
83 | container: {
84 | flex: 1,
85 | padding: 35,
86 | },
87 | inputGroup: {
88 | flex: 1,
89 | padding: 0,
90 | marginBottom: 15,
91 | borderBottomWidth: 1,
92 | borderBottomColor: "#cccccc",
93 | },
94 | loader: {
95 | left: 0,
96 | right: 0,
97 | top: 0,
98 | bottom: 0,
99 | position: "absolute",
100 | alignItems: "center",
101 | justifyContent: "center",
102 | },
103 | });
104 |
105 | export default AddUserScreen;
106 |
--------------------------------------------------------------------------------
/screens/UserDetailScreen.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import {
3 | ScrollView,
4 | Button,
5 | View,
6 | Alert,
7 | ActivityIndicator,
8 | StyleSheet,
9 | } from "react-native";
10 | import { TextInput } from "react-native-gesture-handler";
11 |
12 | import firebase from "../database/firebase";
13 |
14 | const UserDetailScreen = (props) => {
15 | const initialState = {
16 | id: "",
17 | name: "",
18 | email: "",
19 | phone: "",
20 | };
21 |
22 | const [user, setUser] = useState(initialState);
23 | const [loading, setLoading] = useState(true);
24 |
25 | const handleTextChange = (value, prop) => {
26 | setUser({ ...user, [prop]: value });
27 | };
28 |
29 | const getUserById = async (id) => {
30 | const dbRef = firebase.db.collection("users").doc(id);
31 | const doc = await dbRef.get();
32 | const user = doc.data();
33 | setUser({ ...user, id: doc.id });
34 | setLoading(false);
35 | };
36 |
37 | const deleteUser = async () => {
38 | setLoading(true)
39 | const dbRef = firebase.db
40 | .collection("users")
41 | .doc(props.route.params.userId);
42 | await dbRef.delete();
43 | setLoading(false)
44 | props.navigation.navigate("UsersList");
45 | };
46 |
47 | const openConfirmationAlert = () => {
48 | Alert.alert(
49 | "Removing the User",
50 | "Are you sure?",
51 | [
52 | { text: "Yes", onPress: () => deleteUser() },
53 | { text: "No", onPress: () => console.log("canceled") },
54 | ],
55 | {
56 | cancelable: true,
57 | }
58 | );
59 | };
60 |
61 | const updateUser = async () => {
62 | const userRef = firebase.db.collection("users").doc(user.id);
63 | await userRef.set({
64 | name: user.name,
65 | email: user.email,
66 | phone: user.phone,
67 | });
68 | setUser(initialState);
69 | props.navigation.navigate("UsersList");
70 | };
71 |
72 | useEffect(() => {
73 | getUserById(props.route.params.userId);
74 | }, []);
75 |
76 | if (loading) {
77 | return (
78 |
79 |
80 |
81 | );
82 | }
83 |
84 | return (
85 |
86 |
87 | handleTextChange(value, "name")}
93 | />
94 |
95 |
96 | handleTextChange(value, "email")}
102 | />
103 |
104 |
105 | handleTextChange(value, "phone")}
111 | />
112 |
113 |
114 |
120 |
121 |
123 |
124 | );
125 | };
126 |
127 | const styles = StyleSheet.create({
128 | container: {
129 | flex: 1,
130 | padding: 35,
131 | },
132 | loader: {
133 | left: 0,
134 | right: 0,
135 | top: 0,
136 | bottom: 0,
137 | position: "absolute",
138 | alignItems: "center",
139 | justifyContent: "center",
140 | },
141 | inputGroup: {
142 | flex: 1,
143 | padding: 0,
144 | marginBottom: 15,
145 | borderBottomWidth: 1,
146 | borderBottomColor: "#cccccc",
147 | },
148 | btn: {
149 | marginBottom: 7,
150 | },
151 | });
152 |
153 | export default UserDetailScreen;
154 |
--------------------------------------------------------------------------------