0
0
React Nativemobile~20 mins

Firestore CRUD operations in React Native - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Firestore CRUD Demo
A simple React Native screen to create, read, update, and delete items in Firestore.
Target UI
-------------------------
| Firestore CRUD Demo    |
-------------------------
| [Input: New Item]      |
| [Add Item Button]      |
|-----------------------|
| Items List:            |
| 1. Item 1 [Edit][Del] |
| 2. Item 2 [Edit][Del] |
| ...                   |
-------------------------
TextInput to enter new item text
Button to add new item to Firestore
Display list of items from Firestore in real-time
Each item shows text with Edit and Delete buttons
Edit button allows changing item text inline
Delete button removes item from Firestore
Starter Code
React Native
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, Button, FlatList, TouchableOpacity } from 'react-native';
import firestore from '@react-native-firebase/firestore';

export default function FirestoreCRUD() {
  const [newItem, setNewItem] = useState('');
  const [items, setItems] = useState([]);

  useEffect(() => {
    // TODO: Subscribe to Firestore collection and update items state
  }, []);

  const addItem = () => {
    // TODO: Add new item to Firestore
  };

  const deleteItem = (id) => {
    // TODO: Delete item from Firestore by id
  };

  const editItem = (id, newText) => {
    // TODO: Update item text in Firestore
  };

  return (
    <View style={{ flex: 1, padding: 20 }}>
      <Text style={{ fontSize: 24, marginBottom: 10 }}>Firestore CRUD Demo</Text>
      <TextInput
        placeholder="New Item"
        value={newItem}
        onChangeText={setNewItem}
        style={{ borderWidth: 1, padding: 8, marginBottom: 10 }}
      />
      <Button title="Add Item" onPress={addItem} />
      <FlatList
        data={items}
        keyExtractor={item => item.id}
        renderItem={({ item }) => (
          <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 10 }}>
            <Text>{item.text}</Text>
            <View style={{ flexDirection: 'row' }}>
              <TouchableOpacity onPress={() => {/* TODO: Trigger edit */}}>
                <Text style={{ color: 'blue', marginRight: 10 }}>Edit</Text>
              </TouchableOpacity>
              <TouchableOpacity onPress={() => deleteItem(item.id)}>
                <Text style={{ color: 'red' }}>Delete</Text>
              </TouchableOpacity>
            </View>
          </View>
        )}
      />
    </View>
  );
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
React Native
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, Button, FlatList, TouchableOpacity } from 'react-native';
import firestore from '@react-native-firebase/firestore';

export default function FirestoreCRUD() {
  const [newItem, setNewItem] = useState('');
  const [items, setItems] = useState([]);
  const [editingId, setEditingId] = useState(null);
  const [editingText, setEditingText] = useState('');

  useEffect(() => {
    const unsubscribe = firestore()
      .collection('items')
      .orderBy('createdAt', 'desc')
      .onSnapshot(querySnapshot => {
        const list = [];
        querySnapshot.forEach(doc => {
          list.push({ id: doc.id, ...doc.data() });
        });
        setItems(list);
      });
    return () => unsubscribe();
  }, []);

  const addItem = () => {
    if (newItem.trim() === '') return;
    firestore()
      .collection('items')
      .add({ text: newItem.trim(), createdAt: firestore.FieldValue.serverTimestamp() });
    setNewItem('');
  };

  const deleteItem = (id) => {
    firestore().collection('items').doc(id).delete();
  };

  const startEditing = (id, text) => {
    setEditingId(id);
    setEditingText(text);
  };

  const saveEdit = (id) => {
    if (editingText.trim() === '') return;
    firestore().collection('items').doc(id).update({ text: editingText.trim() });
    setEditingId(null);
    setEditingText('');
  };

  const cancelEdit = () => {
    setEditingId(null);
    setEditingText('');
  };

  return (
    <View style={{ flex: 1, padding: 20 }}>
      <Text style={{ fontSize: 24, marginBottom: 10 }}>Firestore CRUD Demo</Text>
      <TextInput
        placeholder="New Item"
        value={newItem}
        onChangeText={setNewItem}
        style={{ borderWidth: 1, padding: 8, marginBottom: 10 }}
        accessibilityLabel="New item input"
      />
      <Button title="Add Item" onPress={addItem} accessibilityLabel="Add item button" />
      <FlatList
        data={items}
        keyExtractor={item => item.id}
        renderItem={({ item }) => (
          <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 10, alignItems: 'center' }}>
            {editingId === item.id ? (
              <>
                <TextInput
                  value={editingText}
                  onChangeText={setEditingText}
                  style={{ borderWidth: 1, padding: 4, flex: 1, marginRight: 10 }}
                  accessibilityLabel={`Edit input for ${item.text}`}
                />
                <Button title="Save" onPress={() => saveEdit(item.id)} accessibilityLabel="Save edit button" />
                <Button title="Cancel" onPress={cancelEdit} accessibilityLabel="Cancel edit button" />
              </>
            ) : (
              <>
                <Text style={{ flex: 1 }}>{item.text}</Text>
                <TouchableOpacity onPress={() => startEditing(item.id, item.text)} accessibilityRole="button" accessibilityLabel={`Edit button for ${item.text}`}>
                  <Text style={{ color: 'blue', marginRight: 10 }}>Edit</Text>
                </TouchableOpacity>
                <TouchableOpacity onPress={() => deleteItem(item.id)} accessibilityRole="button" accessibilityLabel={`Delete button for ${item.text}`}>
                  <Text style={{ color: 'red' }}>Delete</Text>
                </TouchableOpacity>
              </>
            )}
          </View>
        )}
      />
    </View>
  );
}

This React Native component connects to Firestore to perform CRUD operations on a collection named 'items'.

  • We use useEffect to subscribe to real-time updates from Firestore and update the items state.
  • addItem adds a new document with the entered text and a timestamp.
  • deleteItem removes a document by its ID.
  • Editing is handled by tracking the editingId and editingText. When editing, an input and Save/Cancel buttons appear inline.
  • Accessibility labels are added for better screen reader support.
  • The UI updates live as Firestore data changes.

This approach gives a simple, clear example of Firestore CRUD in React Native.

Final Result
Completed Screen
-------------------------
| Firestore CRUD Demo    |
-------------------------
| [Input: New Item]      |
| [Add Item Button]      |
|-----------------------|
| Items List:            |
| 1. Item 1 [Edit][Del] |
| 2. Item 2 [Edit][Del] |
| ...                   |
-------------------------
User types text in the input and taps 'Add Item' to save it to Firestore.
Items list updates live showing all saved items.
Tapping 'Edit' replaces item text with an input and shows 'Save' and 'Cancel' buttons.
Tapping 'Save' updates the item text in Firestore and returns to normal view.
Tapping 'Cancel' discards changes and returns to normal view.
Tapping 'Delete' removes the item from Firestore and the list updates.
Stretch Goal
Add a pull-to-refresh feature to reload the items list manually.
💡 Hint
Use FlatList's refreshing and onRefresh props to implement pull-to-refresh.