React
Firebase
Web Dev
Getting Started with React + Firebase: Build a Real-time CRUD App
đ Table of Contents
1. Prerequisites
Before we begin, make sure you have the following installed on your machine:
- Node.js v18+ â Download from nodejs.org
- npm or yarn â Comes with Node.js
- A Google account â For Firebase console access
- VS Code (recommended) â With ESLint and Prettier extensions
This tutorial uses React 18 with Vite as the build tool (faster than Create React App) and Firebase v10 (modular SDK).
2. Project Setup
Let's scaffold a new React project using Vite:
bash
# Create new Vite + React project npm create vite@latest my-firebase-app -- --template react cd my-firebase-app npm install # Install Firebase SDK npm install firebase # Start development server npm run dev
Your project structure should look like this:
text
my-firebase-app/ âââ src/ â âââ components/ â âââ firebase.js â Firebase config â âââ App.jsx â âââ main.jsx âââ index.html âââ package.json
3. Firebase Configuration
Go to console.firebase.google.com, create a new project, then add a Web App. Copy your config object:
javascript
// src/firebase.js
import { initializeApp } from 'firebase/app';
import { getDatabase } from 'firebase/database';
import { getAuth } from 'firebase/auth';
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT.firebaseapp.com",
databaseURL: "https://YOUR_PROJECT-default-rtdb.firebaseio.com",
projectId: "YOUR_PROJECT",
storageBucket: "YOUR_PROJECT.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};
const app = initializeApp(firebaseConfig);
export const db = getDatabase(app);
export const auth = getAuth(app);
Never commit your Firebase config to a public GitHub repo. Use environment variables:
.env.local with VITE_FIREBASE_API_KEY=... and access via import.meta.env.VITE_FIREBASE_API_KEY.4. React Components
Create a simple task list component that reads and writes to Firebase:
jsx
// src/components/TaskList.jsx
import { useState, useEffect } from 'react';
import { db } from '../firebase';
import { ref, onValue, push, remove } from 'firebase/database';
function TaskList() {
const [tasks, setTasks] = useState([]);
const [input, setInput] = useState('');
useEffect(() => {
const tasksRef = ref(db, 'tasks');
const unsubscribe = onValue(tasksRef, (snapshot) => {
const data = snapshot.val();
if (data) {
const taskList = Object.entries(data).map(([id, val]) => ({
id,
...val
}));
setTasks(taskList);
} else {
setTasks([]);
}
});
// Cleanup listener on unmount
return () => unsubscribe();
}, []);
const addTask = async () => {
if (!input.trim()) return;
await push(ref(db, 'tasks'), {
text: input,
createdAt: Date.now(),
done: false
});
setInput('');
};
const deleteTask = async (id) => {
await remove(ref(db, `tasks/${id}`));
};
return (
<div className="task-container">
<div className="task-input-row">
<input
value={input}
onChange={e => setInput(e.target.value)}
onKeyDown={e => e.key === 'Enter' && addTask()}
placeholder="Add a new task..."
/>
<button onClick={addTask}>Add</button>
</div>
<ul>
{tasks.map(task => (
<li key={task.id}>
<span>{task.text}</span>
<button onClick={() => deleteTask(task.id)}>đī¸</button>
</li>
))}
</ul>
</div>
);
}
export default TaskList;
5. CRUD Operations
Firebase Realtime Database uses these core functions from the modular SDK:
Read (Real-time listener)
javascript
import { ref, onValue, get } from 'firebase/database';
// Real-time listener (updates on every change)
onValue(ref(db, 'tasks'), (snapshot) => {
console.log(snapshot.val());
});
// One-time read
const snapshot = await get(ref(db, 'tasks'));
console.log(snapshot.val());
Write, Update, Delete
javascript
import { ref, set, push, update, remove } from 'firebase/database';
// Create (auto-generated ID)
await push(ref(db, 'tasks'), { text: 'Buy groceries', done: false });
// Create (custom ID)
await set(ref(db, 'users/user123'), { name: 'Alfan', role: 'admin' });
// Update (partial)
await update(ref(db, 'tasks/-NxxxxID'), { done: true });
// Delete
await remove(ref(db, 'tasks/-NxxxxID'));
Use
push() for lists (tasks, posts, messages) â it generates a time-based unique key. Use set() when you want to define the path (e.g., user profile keyed by UID).6. Adding Authentication
javascript
import { auth } from '../firebase';
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signInWithPopup,
GoogleAuthProvider,
onAuthStateChanged,
signOut
} from 'firebase/auth';
// Register with email
await createUserWithEmailAndPassword(auth, email, password);
// Login with email
await signInWithEmailAndPassword(auth, email, password);
// Google login
const provider = new GoogleAuthProvider();
await signInWithPopup(auth, provider);
// Listen to auth state
onAuthStateChanged(auth, (user) => {
if (user) {
console.log('Logged in:', user.uid, user.email);
} else {
console.log('Logged out');
}
});
// Logout
await signOut(auth);
7. Deploy to Netlify
Build and deploy your app to Netlify in minutes:
bash
# Build the app npm run build # Install Netlify CLI globally npm install -g netlify-cli # Login and deploy netlify login netlify deploy --prod --dir=dist
Add your Firebase environment variables in Netlify Dashboard â Site Settings â Environment Variables. This keeps your API keys secure and out of your codebase.
đ
You've built your first React + Firebase app!
Continue learning with these next steps: