Firebase と React を使用して独自のいいねとコメントのシステムを構築する方法
31091 ワード
React アプリに関する私の ToDo 項目の 1 つは、静的な Web サイトにパフォーマンス優先の動的なコメントといいね! システムを導入することでした.なんで?それは、コンテンツを超えて、ユーザーの関与を促す機能を追加する機能をもたらすからです.
そこで、 Firebase 、 TailwindCSS 、および React を使用してシステムの作成に着手しました. TailwindCSS は強制ではありませんが、私のお気に入りのライブラリです.始めましょう.
次のコマンドを使用して、Firebase (クライアント側) をインストールします.
次の構成で firebase.js を作成します.
like.js ファイルを作成します.
ブログページのスラッグを受け取る getLikes 関数と、必要に応じてコールバック関数を追加します.
ブログページのスラッグを受け取る postLike 関数と、必要に応じてコールバック関数を追加します.
comment.js ファイルを作成します.
ブログページのスラッグを受け取る getComments 関数と、必要に応じてコールバック関数を追加します.
ブログページのスラッグを受け取る writeComment 関数と、必要に応じてコールバック関数を追加します.
表示するコメントのセットを取り込む LoadComments 関数の作成
ブログページのスラッグを取り込む WriteComment コンポーネントと、表示される新しいコメントセットを設定するための setComments を作成します.
動的ブログの [slug].js ファイルにコンポーネントをロードします.
私の blog page で例を見ることができます!ソースコードは here で入手できます.
Cusdis と Disqus はどちらも Cumulative Layout Shift (CLS) に大きな影響を与えるため、パフォーマンス フレンドリではありません。
そこで、 Firebase 、 TailwindCSS 、および React を使用してシステムの作成に着手しました. TailwindCSS は強制ではありませんが、私のお気に入りのライブラリです.始めましょう.
Firebase の設定
npm i firebase
// File: @/lib/firebase.js
import 'firebase/firestore'
import firebase from 'firebase/app'
// More about firebase config on https://firebase.google.com/docs/web/setup#config-object
var firebaseConfig = {
apiKey: '',
authDomain: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
}
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig)
} else {
firebase.app()
}
export const firestore = firebase.firestore()
export default firebase
類似コンポーネントの作成
// File: components/blog/like.js
import { firestore } from '@/lib/firebase'
export const getLikes = (slug, callBackFunction) => {
firestore
.collection('likes')
.doc(slug)
.get()
.then((doc) => {
if (doc.exists) {
callBackFunction(Object.keys(doc.data()).length)
}
})
.catch((err) => {
console.error(err)
})
}
export const postLike = (slug, callBackFunction) => {
fetch('https://api.ipify.org/?format=json', {
method: 'GET',
})
.then((res) => res.json())
.then((res) => {
firestore
.collection('likes')
.doc(slug)
.set(
{
[res['ip']]: null,
},
{ merge: true }
)
.then(callBackFunction)
})
.catch((err) => {
console.error(err)
})
}
コメント コンポーネントの作成
// File: components/blog/comments.js
import { useState } from 'react'
import firebase, { firestore } from '@/lib/firebase'
export const getComments = (slug, callBackFunction) => {
firestore
.collection('comments')
.get()
.then((snapshot) => {
const posts = snapshot.docs
.map((doc) => doc.data())
.filter((doc) => doc.slug === slug)
.map((doc) => {
return { id: doc.id, ...doc }
})
callBackFunction(posts)
})
.catch((err) => {
console.log(err)
})
}
export const writeComment = (name, slug, content, email, callBackFunction) => {
let temp = {
name,
slug,
content,
time: firebase.firestore.Timestamp.fromDate(new Date()),
}
if (email.length > 0) temp['email'] = email
firestore
.collection('comments')
.add(temp)
.then(() => {
callBackFunction()
})
.catch((err) => {
console.error(err)
})
}
export const LoadComments = ({ comments }) => {
return comments
.sort((a, b) =>
a.time.toDate().getTime() > b.time.toDate().getTime() ? -1 : 1
)
.map((item) => (
<div
key={item.time.seconds}
className="border dark:border-gray-500 rounded p-5 w-full mt-5 flex flex-col"
>
<span className="text-lg text-gray-500 dark:text-gray-300 font-medium">
{item.name} · {item.time.toDate().toDateString()}
</span>
<span className="mt-3 text-md text-gray-500 dark:text-gray-300">
{item.content}
</span>
</div>
))
}
const WriteComment = ({ slug, setComments }) => {
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [comment, setComment] = useState('')
return (
<form
onSubmit={(e) => {
e.preventDefault()
writeComment(name, slug, comment, email, () =>
getComments(slug, setComments)
)
setName('')
setEmail('')
setComment('')
}}
className="mt-10 flex flex-col w-full"
>
<h1 className="font-semibold text-lg">Write a comment</h1>
<div className="flex flex-col sm:flex-row sm:space-x-5 items-start">
<input
required
value={name}
placeholder="Name*"
onChange={(e) => setName(e.target.value)}
className="mt-5 w-full sm:w-1/2 appearance-none outline-none ring-0 px-5 py-2 border dark:hover:border-white hover:border-black rounded hover:shadow text-black dark:bg-black dark:text-gray-300 dark:border-gray-500"
/>
<div className="mt-5 w-full sm:w-1/2 flex flex-col space-y-1">
<input
value={email}
placeholder="Email (Optional)"
onChange={(e) => setEmail(e.target.value)}
className="w-full appearance-none outline-none ring-0 px-5 py-2 border dark:hover:border-white hover:border-black rounded hover:shadow text-black dark:bg-black dark:text-gray-300 dark:border-gray-500"
/>
<span className="text-sm text-gray-400">
Email will remain confidential.
</span>
</div>
</div>
<textarea
required
value={comment}
onChange={(e) => setComment(e.target.value)}
placeholder={'Comment*\nMaximum of 500 characters.'}
className="mt-5 appearance-none outline-none ring-0 pt-5 px-5 pb-10 border dark:hover:border-white hover:border-black rounded hover:shadow text-black dark:bg-black dark:text-gray-300 dark:border-gray-500"
/>
<button
type="submit"
className="w-[200px] appearance-none mt-5 py-2 px-5 text-center rounded border hover:bg-gray-100 dark:hover:bg-[#28282B] dark:border-gray-500"
>
Post a comment
</button>
</form>
)
}
export default WriteComment
動的ブログ コンポーネントの作成
import WriteComment, {
getComments,
LoadComments,
} from '@/components/blog/comments'
export default function Post({ post }) {
const [comments, setComments] = useState([])
return <>
<WriteComment setComments={setComments} slug={post.slug} />
<div className="mt-10 pt-10 w-full border-t dark:border-gray-500">
<button
onClick={() => getComments(post.slug, setComments)}
className="w-[200px] appearance-none py-2 px-5 text-center rounded border hover:bg-gray-100 dark:hover:bg-[#28282B] dark:border-gray-500"
>
Load Comments
</button>
</div>
<LoadComments comments={comments} />
</>
}
例
私の blog page で例を見ることができます!ソースコードは here で入手できます.
Reference
この問題について(Firebase と React を使用して独自のいいねとコメントのシステムを構築する方法), 我々は、より多くの情報をここで見つけました https://dev.to/digitalplayer1125/how-to-build-your-own-likes-and-comments-system-with-firebase-and-react-30o3テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol