Firebase Firestore در React: ذخیره و بازیابی داده های کاربر

با استفاده از احراز هویت Firebase برای ایجاد یک برنامه کامل داده محور
در آموزش قبلی خود ، ما با موفقیت تأیید هویت Firebase را در یک برنامه React اجرا کردیم. اکنون که کاربران می توانند ثبت نام و ورود به سیستم داشته باشند ، مرحله منطقی بعدی این است که به آنها اجازه دهد داده های خود را ذخیره و مدیریت کنند. در این آموزش ، ما Firebase Firestore (پایگاه داده NOSQL Firebase) را ادغام می کنیم تا یک سیستم پست وبلاگ ساده ایجاد کنیم که کاربران معتبر بتوانند پست های وبلاگ خود را ایجاد ، ذخیره و بازیابی کنند.
فهرست مطالب
- آنچه ما می سازیم
- درک Firebase Firestore
- پیش نیازهای
- مرحله 1: Firestore را در کنسول Firebase فعال کنید
- مرحله 2: پیکربندی Firebase را به روز کنید
- مرحله 3: درک ساختار داده های Firestore
- مرحله 4: مؤلفه فرم ارسال وبلاگ را ایجاد کنید
- مرحله 5: مؤلفه لیست پست های وبلاگ را ایجاد کنید
- مرحله 6: مؤلفه خانه را به روز کنید
- مرحله 7: برای اجزای جدید یک ظاهر طراحی شده اضافه کنید
- مرحله 8: آزمایش جریان کامل
- درک نحوه کار Firestore
- قوانین امنیتی
- مسائل مشترک و عیب یابی
- مراحل بعدی
- پایان
آنچه ما می سازیم
با تکیه بر سیستم احراز هویت ما ، ما اضافه خواهیم کرد:
- فرم برای کاربران برای ایجاد پست های وبلاگ با عنوان ، محتوا و دسته بندی
- ذخیره سازی در زمان واقعی پست های وبلاگ در Firebase Firestore
- یک نمایش لیست برای نمایش همه پست های وبلاگ کاربر
- به روزرسانی های زمان واقعی هنگام افزودن پست های جدید
- جداسازی داده های خاص کاربر (کاربران فقط پست های خود را می بینند)
درک Firebase Firestore
قبل از اینکه وارد کد شویم ، بیایید بفهمیم Firebase Firestore چیست و چرا از آن استفاده می کنیم.
Firestore چیست؟
Firebase Firestore یک پایگاه داده انعطاف پذیر و مقیاس پذیر سند NOSQL برای توسعه موبایل ، وب و سرور است. بر خلاف پایگاه داده های سنتی SQL با جداول و ردیف ، Firestore داده ها را در اسناد و مجموعه ها ذخیره می کند.
مفاهیم کلیدی:
- اسناد: سوابق فردی که حاوی داده ها به عنوان جفت ارزش کلیدی هستند
- مجموعه: گروه های اسناد (مشابه جداول در SQL)
- به روزرسانی های زمان واقعی: Firestore هنگام تغییر داده می تواند برنامه شما را به شما اطلاع دهد
- پشتیبانی آفلاین: حتی وقتی کاربران آفلاین هستند کار می کند
- قوانین امنیتی: قوانین سمت سرور که دسترسی به داده ها را کنترل می کنند
چرا از Firestore استفاده می کنیم؟
- همگام سازی در زمان واقعی: تغییرات بلافاصله در تمام دستگاه های متصل ظاهر می شوند
- مقیاس پذیری: به طور خودکار با برنامه خود مقیاس می کند
- امنیت: ادغام احراز هویت داخلی و قوانین امنیتی
- پشتیبانی آفلاین: هنگام بازگشت آنلاین ، یکپارچه آفلاین و همگام سازی کار می کند
پیش نیازهای
- آموزش تأیید اعتبار قبلی Firebase را تکمیل کرد
- درک اساسی قلاب های React (Usestate ، UseEffect)
- پروژه Firebase شما با تأیید اعتبار از قبل تنظیم شده است
مرحله 1: Firestore را در کنسول Firebase فعال کنید
اول ، ما باید Firestore را در پروژه Firebase خود فعال کنیم:
- به کنسول Firebase خود بروید
- پروژه موجود خود را انتخاب کنید
- در نوار کناری چپ ، روی “پایگاه داده Firestore” کلیک کنید
- روی “ایجاد پایگاه داده” کلیک کنید
- “شروع در حالت آزمون” را هم اکنون انتخاب کنید (بعداً در مورد قوانین امنیتی بحث خواهیم کرد)
- مکانی را برای پایگاه داده خود انتخاب کنید (یکی از نزدیکترین کاربران خود را انتخاب کنید)
- روی “انجام شده” کلیک کنید
مهم: شروع در حالت آزمون به این معنی است که هرکسی می تواند به پایگاه داده شما بخواند و بنویسد. ما بعداً با قوانین امنیتی مناسب این مسئله را تضمین خواهیم کرد.
مرحله 2: پیکربندی Firebase را به روز کنید
ما باید توابع Firestore را در پرونده پیکربندی Firebase موجود خود وارد کنیم:
// src/firebase.js
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
// Your existing Firebase config
apiKey: "your-api-key",
authDomain: "your-project-id.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-project-id.appspot.com",
messagingSenderId: "your-messaging-sender-id",
appId: "your-app-id"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const db = getFirestore(app);
export default app;
مرحله 3: درک ساختار داده های Firestore
قبل از نوشتن کد ، بیایید ساختار داده خود را برنامه ریزی کنیم. برای پست های وبلاگ ما ، ما از این ساختار استفاده خواهیم کرد:
Collection: "posts"
Document ID: auto-generated
Document Data: {
title: "My First Blog Post",
content: "This is the content of my blog post...",
category: "Technology",
authorId: "user-uid-from-auth",
authorEmail: "user@example.com",
createdAt: timestamp,
updatedAt: timestamp
}
چرا این ساختار؟
- نویسنده: برای امنیت و فیلتر ، پست ها را به کاربران خاص پیوند می دهد
- تناقضات زمانی: هنگامی که پست ها ایجاد و اصلاح شدند ، پیگیری کنید
- نویسنده: راهی آسان برای نمایش کسانی که پست را نوشتند
- دسته: امکان فیلتر کردن و ویژگی های آینده را در آینده فراهم می کند
مرحله 4: مؤلفه فرم ارسال وبلاگ را ایجاد کنید
بیایید یک مؤلفه ایجاد کنیم که به کاربران امکان ایجاد پست های جدید وبلاگ را می دهد:
// src/components/CreatePost.js
import React, { useState } from 'react';
import { collection, addDoc, serverTimestamp } from 'firebase/firestore';
import { db, auth } from '../firebase';
function CreatePost({ onPostCreated }) {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const [category, setCategory] = useState('General');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [success, setSuccess] = useState('');
const categories = ['General', 'Technology', 'Lifestyle', 'Travel', 'Food', 'Other'];
async function handleSubmit(e) {
e.preventDefault();
if (!title.trim() || !content.trim()) {
setError('Please fill in both title and content');
return;
}
if (!auth.currentUser) {
setError('You must be logged in to create a post');
return;
}
try {
setError('');
setSuccess('');
setLoading(true);
// Add document to the "posts" collection
const docRef = await addDoc(collection(db, 'posts'), {
title: title.trim(),
content: content.trim(),
category: category,
authorId: auth.currentUser.uid,
authorEmail: auth.currentUser.email,
createdAt: serverTimestamp(),
updatedAt: serverTimestamp()
});
console.log('Document written with ID: ', docRef.id);
// Reset form
setTitle('');
setContent('');
setCategory('General');
setSuccess('Post created successfully!');
// Notify parent component
if (onPostCreated) {
onPostCreated();
}
} catch (error) {
console.error('Error adding document: ', error);
setError('Failed to create post: ' + error.message);
} finally {
setLoading(false);
}
}
return (
<div className="create-post-container">
<h3>Create New Blog Post</h3>
{error && <div className="error-message">{error}</div>}
{success && <div className="success-message">{success}</div>}
<form onSubmit={handleSubmit} className="create-post-form">
<div className="form-group">
<label htmlFor="title">Title</label>
<input
type="text"
id="title"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Enter your blog post title"
maxLength={100}
required
/>
<small>{title.length}/100 characterssmall>
</div>
<div className="form-group">
<label htmlFor="category">Category</label>
<select
id="category"
value={category}
onChange={(e) => setCategory(e.target.value)}
>
{categories.map(cat => (
<option key={cat} value={cat}>{cat}</option>
))}
</select>
</div>
<div className="form-group">
<label htmlFor="content">Content</label>
<textarea
id="content"
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="Write your blog post content here..."
rows={8}
maxLength={2000}
required
/>
<small>{content.length}/2000 characterssmall>
</div>
<button
type="submit"
disabled={loading}
className="submit-button"
>
{loading ? 'Publishing...' : 'Publish Post'}
</button>
</form>
</div>
);
}
export default CreatePost;
مرحله 5: مؤلفه لیست پست های وبلاگ را ایجاد کنید
حال بیایید یک مؤلفه برای نمایش همه پست های وبلاگ کاربر ایجاد کنیم:
// src/components/PostsList.js
import React, { useState, useEffect } from 'react';
import { collection, query, where, orderBy, onSnapshot } from 'firebase/firestore';
import { db, auth } from '../firebase';
function PostsList({ refreshTrigger }) {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
useEffect(() => {
if (!auth.currentUser) {
setLoading(false);
return;
}
// Create a query to get posts for the current user, ordered by creation date
const q = query(
collection(db, 'posts'),
where('authorId', '==', auth.currentUser.uid),
orderBy('createdAt', 'desc')
);
// Set up real-time listener
const unsubscribe = onSnapshot(q,
(querySnapshot) => {
const postsArray = [];
querySnapshot.forEach((doc) => {
postsArray.push({
id: doc.id,
...doc.data()
});
});
setPosts(postsArray);
setLoading(false);
setError('');
},
(error) => {
console.error('Error fetching posts:', error);
setError('Failed to load posts: ' + error.message);
setLoading(false);
}
);
// Cleanup subscription on unmount
return () => unsubscribe();
}, [refreshTrigger]);
function formatDate(timestamp) {
if (!timestamp) return 'Unknown date';
// Handle Firestore timestamp
const date = timestamp.toDate ? timestamp.toDate() : new Date(timestamp);
return date.toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
if (loading) {
return <div className="loading">Loading your posts...</div>;
}
if (error) {
return <div className="error-message">{error}</div>;
}
if (posts.length === 0) {
return (
<div className="no-posts">
<h3>No Blog Posts Yet</h3>
<p>You haven't created any blog posts yet. Create your first post above!
) ؛ } بازگشت (
پست های وبلاگ شما ({posts.l طول})
{posts.map ((پست) => (
{post.title}
{post.category}
{post.content.l طول> 150؟ post.content.substring (0 ، 150) + '…'
: post.content}
ایجاد شده: {formatdate (post.createdat)}
{post.updatedat && post.updatedat! == post.createdat && (
به روز شده: {formatDate (post.updatedat)}
)}
))}
) ؛ } صادرات لیست پیش فرض لیست ؛
بیایید مؤلفه خانه خود را به روز کنیم تا هم فرم ایجاد پست و هم لیست پست ها را درج کنیم:
در حال حاضر ، پایگاه داده ما در حالت تست است ، به این معنی که هر کسی می تواند داده را بخواند و بنویسد. بیایید قوانین امنیتی مناسب را تنظیم کنیم:
خطا: “مجوزهای از دست رفته یا ناکافی”
راه حل: بررسی کنید که قوانین امنیتی شما به کاربر فعلی امکان دسترسی به داده ها را می دهد
خطا: پست ها بلافاصله پس از ایجاد ظاهر نمی شوند
راه حل: اطمینان حاصل کنید که از آن استفاده می کنید onSnapshot()
برای گوش دادن در زمان واقعی ، نه فقط یک بار خواندن
خطا: تاریخ هایی که به عنوان “تاریخ ناشناخته” نشان داده می شوند
راه حل: اطمینان حاصل کنید که هر دو جدول زمانی Firestore و Dates JavaScript را در خود قرار می دهید formatDate
عمل
خطا: پست هایی که برای کاربران معتبر بارگیری نمی شوند
راه حل: اطمینان حاصل کنید auth.currentUser
قبل از ایجاد نمایش داده شدگان Firestore در دسترس است
تبریک می گویم! شما با موفقیت Firebase Firestore را با سیستم تأیید اعتبار React خود یکپارچه کرده اید. اکنون شما یک برنامه کامل دارید که کاربران می توانند:
این بنیاد همه چیز را برای ساختن برنامه های پیچیده تر داده محور فراهم می کند. ترکیبی از احراز هویت Firebase و Firestore بدون مدیریت سرورها ، یک پس زمینه قدرتمند و مقیاس پذیر به شما می دهد.
قابلیت های زمان واقعی Firestore باعث می شود که برنامه شما پاسخگو و مدرن باشد ، در حالی که قوانین امنیتی اطمینان حاصل می کنند که داده های کاربر خصوصی و ایمن باقی مانده است.