React & firebase로 블로그 웹사이트 만드는 방법 -> Series2
40613 단어 webdevfirebasereactjavascript
react 및 firebase로 블로그 웹사이트를 구축하는 이 시리즈에 오신 것을 환영합니다.
마지막 튜토리얼에서 환경을 준비하고
login
및 HomePage
를 생성했습니다.확인하거나 Here too
이 기사에서는 빌드를 완료할 것입니다. 사용자가 이미지와 이미지의 캡션을 추가할 UI를 준비합시다.
다음 코드를 포함할
CreatePost.js
파일을 생성합니다.import React, { useState } from "react";
import { useSelector } from "react-redux";
import { selectUser } from "../features/userSlice";
import { db } from "../utils/firebase";
import firebase from "firebase/compat/app";
const CreatePost = () => {
const user = useSelector(selectUser);
const [postTitle, setPostTitle] = useState("");
const [imageURL, setimageURL] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
db.collection("posts").add({
uid: user.uid,
message: postTitle,
displayName: user?.displayName,
image: imageURL,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
});
setPostTitle("");
setimageURL("");
};
return (
<div className="w-full mx-auto py-3 px-3 border bg-white border-gray-300 rounded-md">
<form className="mx-auto">
<input
value={postTitle}
onChange={(e) => setPostTitle(e.target.value)}
className="rounded-full w-full border outline-2 px-5 py-2 focus:outline-green-600"
type="text"
placeholder="Enter Post Caption"
/>
<input
value={imageURL}
onChange={(e) => setimageURL(e.target.value)}
className="rounded-full mt-6 w-full border outline-2 px-5 py-2 focus:outline-green-600"
type="text"
placeholder="Enter Image Url"
/>
<button onClick={handleSubmit} className="hidden" type="submit">
Hidden Submit
</button>
</form>
</div>
);
};
export default CreatePost;
**참고: **우리의 이미지 입력은 인터넷이나 다른 소스에서 이미지 URL을 붙여넣을 것임을 의미하는 문자열입니다.
입력 필드에서 값을 입력하고 Enter 키를 누르면 데이터가 firestore 데이터베이스에 제출됩니다.
firebase firestore에서 확인하면
posts
라는 새 컬렉션이 생성되었음을 알 수 있습니다.이제 db에서 웹 페이지로 해당 데이터를 가져와야 합니다.
데이터를 가져오기 위해 useEffect() 후크를 사용합니다. 데이터를 가져오고 보관하는 데 도움이 되는 파일
feed.js
을 생성해 보겠습니다.import React, { useState, useEffect } from "react";
import { db } from "../utils/firebase";
import Post from "./Post";
function Feed() {
// fetch posts and store them in an array
const [posts, setPosts] = useState([]);
useEffect(() => {
db.collection("posts")
.orderBy("timestamp", "desc")
.onSnapshot((snapshot) =>
setPosts(snapshot.docs.map((doc) => ({ id: doc.id, data: doc.data() })))
);
}, []);
return (
<div className="feed">
{posts.map((post) => (
<Post
key={post.id}
message={post.data.message}
timestamp={post.data.timestamp}
displayName={post.data.displayName}
image={post.data.image}
likes={post.data.likes}
uid={post.data.uid}
/>
))}
</div>
);
}
export default Feed;
참고: firestore 컬렉션의 모든 게시물을 매핑하기 위해 forEach() ** 함수 대신 map() 함수를 사용했습니다. 이는 **map()이 새로운 기능이기 때문입니다 😊.
이제 Firestore에서 데이터를 가져왔으므로 게시물 세부 정보를 처리하고 웹 페이지에 표시할 파일
post.js
을 생성해 보겠습니다.import React from "react";
function Post({ displayName, image, timestamp, message }) {
return (
<div className="bg-white border border-gray-300 py-3 px-3 mt-3 mb-3 rounded-md">
<div className="flex items-center justify-between border-b-2 pb-2">
<div className="flex items-center space-x-3 ">
<div className="text-center items-center pt-3 bg-green-600 text-white rounded-full w-12 h-12">
{displayName[0]}
</div>
<div className="">
<h3>{displayName}</h3>
<p className="text-xs text-gray-500">
{new Date(timestamp?.toDate()).toUTCString()}
</p>
</div>
</div>
</div>
<div className="mt-3">
<p>{message}</p>
</div>
<div className="mt-5">
<img className="w-full h-56 " src={image} alt="" />
</div>
<div className=" mt-3 flex justify-between items-center w-full">
<div className="cursor-pointer bg-gray-100 hover:bg-gray-200 text-green-600 py-1 px-2">
<p>Like</p>
</div>
<div className="cursor-pointer bg-gray-100 hover:bg-gray-200 text-green-600 py-1 px-2">
<p>Comment</p>
</div>
<div className="cursor-pointer bg-gray-100 hover:bg-gray-200 text-green-600 py-1 px-2">
<p>Share</p>
</div>
</div>
</div>
);
}
export default Post;
참고:
feed.js
파일에서 모든 소품을 가져오고 있습니다.이제 게시물을 보내고 Firestore에서 가져오는 작업이 완료되었습니다.
feed.js
파일을 HomePage.js
파일로 내보내겠습니다.import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { login, logout, selectUser } from "../features/userSlice";
import { auth } from "../utils/firebase";
import CreatePost from "./CreatePost";
import Feed from "./Feed";
import Header from "./Header";
const HomePage = () => {
const user = useSelector(selectUser);
const dispatch = useDispatch();
useEffect(() => {
auth.onAuthStateChanged((userAuth) => {
if (userAuth) {
dispatch(
login({
email: userAuth.email,
uid: userAuth.uid,
displayName: userAuth.displayName,
})
);
} else {
dispatch(logout);
}
});
}, [dispatch]);
return (
<>
<Header />
<div className="flex space-x-10 justify-between w-5/6 mx-auto mt-5">
<div className="hidden h-40 bg-white rounded-md border border-1 border-gray-300 pb-5 md:flex flex-col items-center w-2/6 ">
<img
className=" rounded-t-md h-20 w-full"
src="https://images.unsplash.com/photo-1542831371-29b0f74f9713?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8M3x8Y29kaW5nfGVufDB8fDB8fA%3D%3D&w=1000&q=80"
alt="text"
/>
<div className="text-center items-center pt-3 -mt-7 bg-green-600 text-white rounded-full w-12 h-12">
{user?.displayName[0]}
</div>
<p className="mt-3">{user.displayName}</p>
</div>
<div className="mx-auto w-full">
<CreatePost />
<Feed />
</div>
<div className="hidden bg-white rounded-md border border-1 border-gray-300 pb-5 md:block py-4 px-2 w-2/6 h-80">
<h2>Trending topics</h2>
<div className="text-left items-center pt-3 space-y-5">
<p className="text-sm text-gray-600">#Javascript</p>
<p className="text-sm text-gray-600">#Java</p>
<p className="text-sm text-gray-600">#Typescript</p>
<p className="text-sm text-gray-600">#Python</p>
<p className="text-sm text-gray-600">#Data Science</p>
<p className="text-sm text-gray-600">#Machine Learning</p>
</div>
</div>
</div>
</>
);
};
export default HomePage;
참고: 우리는 홈페이지를 사용하여 응용 프로그램의 스타일을 지정하므로 페이지를
App.js
파일로 내보내고 사용자가 로그인하지 않은 경우 홈페이지를 표시하도록 인증을 처리할 수 있습니다.이제
HomePage.js
파일을 App.js
파일로 가져오겠습니다.import React, { useEffect } from "react";
import { Routes, Route } from "react-router-dom";
import HomePage from "./components/HomePage";
import "./App.css";
import Login from "./components/Login";
import { useDispatch, useSelector } from "react-redux";
import { login, logout, selectUser } from "./features/userSlice";
import { auth } from "./utils/firebase";
function App() {
const dispatch = useDispatch();
const user = useSelector(selectUser);
//validate and keep the user loggedIn
useEffect(() => {
auth.onAuthStateChanged((userAuth) => {
if (userAuth) {
dispatch(
login({
email: userAuth.email,
uid: userAuth.uid,
displayName: userAuth.displayName,
profilePic: userAuth.photoURL,
})
);
} else {
dispatch(logout);
}
});
}, [dispatch]);
return (
<div className="">
<Routes>
{!user ? (
<Route path="/" element={<Login />} />
) : (
<Route path="/" element={<HomePage />} />
)}
</Routes>
</div>
);
}
export default App;
App.js 파일에서 사용자가 인증될 때 경로를 처리하기 위해
react-router-dom
를 사용했습니다.react-router-dom을 설치하려면 다음 명령을 사용하십시오.
npm install react-router-dom
결론
우리는 마침내 react와 firebase로 완벽한 블로그 웹사이트를 만들었습니다. 이 시리즈의 최종 빌드에서는 Firebase에 배포할 것입니다.
이 기사 시리즈는 원래 melbite.com/create-blogging-web-with-react-firebase에 게시되었습니다.
https://melbite.com에서 내 기사를 더 찾을 수 있습니다.
이 아름다운 애플리케이션의 소스 코드를 얻으려면check my github
Reference
이 문제에 관하여(React & firebase로 블로그 웹사이트 만드는 방법 -> Series2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/evansifyke/how-to-create-a-blog-website-with-react-firebase-series2-3jdd텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)