반응형
PedroTech님의 풀스택 강의 13일 차를 참고했습니다.
📌 Users 테이블의 id를 Posts와 연결하기
// ./server/models/Users.js
module.exports = (sequelize, DataTypes) => {
const Users = sequelize.define("Users", {...
});
Users.associate = (models) => {
Users.hasMany(models.Likes, {...
});
// Users의 id를 Posts와 1:N 관계로 연결합니다.
Users.hasMany(models.Posts, {
onDelete: "cascade",
});
};
return Users;
};
Users 테이블의 id와 Posts 테이블의 id를1:N 관계로 연결해 줍니다.
📌 글 작성하는 화면 수정하기
// ./client/src/pages/createPost.js
import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
import "./CreatePost.css";
import * as Yup from "yup";
import axios from "axios";
import { useNavigate } from "react-router-dom";
function CreatePost() {
let navigate = useNavigate();
const initialValues = {
title: "",
postText: "",
};
const validationSchema = Yup.object().shape({
title: Yup.string().required(),
postText: Yup.string().required(),
});
// Posts 테이블에 사용자 정보가 필요하기에 headers로 전달해줍니다.
const onSubmit = (data) => {
axios
.post("http://localhost:3001/posts", data, {
headers: {
accessTocken: localStorage.getItem("accessTocken"),
},
})
.then(() => {
navigate("/");
});
};
return (
{/*
사용자 이름은 따로 추가해줄 것이기 때문에
사용자명 입력창은 삭제합니다.
*/}
<div className="createPostPage">
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={validationSchema}
>
<Form>
<label htmlFor="inputTitle">Title: </label>
<ErrorMessage name="title" component="span" />
<Field
autoComplete="off"
id="inputTitle"
className="createPostItem"
name="title"
placeholder="(Ex. Title...)"
/>
<label htmlFor="inputContent">Post: </label>
<ErrorMessage name="postText" component="span" />
<Field
autoComplete="off"
id="inputContent"
className="createPostItem"
name="postText"
placeholder="(Ex. Content...)"
/>
<button type="submit" className="createPostBtn">
Create Post
</button>
</Form>
</Formik>
</div>
);
}
export default CreatePost;
기존과 달라진 점 설명
1. 사용자명 입력창, 변수 제거: router에서 따로 사용자 이름과 id를 저장하기 때문에 제거했습니다.
2. 작성 시 사용자 정보 전달: axios.post 할 때 headers로 사용자 정보를 전달해 줘서 지금 로그인되어있는 사용자가 누구인지 식별 가능합니다.
📌 글 작성한 뒤 전달되는 router 수정하기(Posts)
// ./server/routes/Posts.js
const express = require("express");
const router = express.Router();
const { Posts, Likes } = require("../models");
const { validateTocken } = require("../middlewares/AuthMiddleware");
router.get("/", async (req, res) => {...
});
router.get("/byId/:id", async (req, res) => {...
});
router.get("/byuserId/:id", async (req, res) => {...
});
// 사용자 이름과 UserId를 추가해서 저장해줍니다.
router.post("/", validateTocken, async (req, res) => {
const post = req.body;
post.username = req.user.username;
post.UserId = req.user.id;
await Posts.create(post); //squelize function create
res.json(post);
});
module.exports = router;
사용자가 작성한 글이 무엇인지 구별하기 위해 사용자 이름과 id를 추가해 줍니다.
사용자 정보를 headers로 전달된 데이터에서 가져옵니다.
📌 사용자 정보 가져오는 router 생성하기(Users)
// ./server/routes/Users.js
const express = require("express");
const router = express.Router();
const { Users } = require("../models");
const bcrypt = require("bcrypt");
const { sign } = require("jsonwebtoken");
const { validateTocken } = require("../middlewares/AuthMiddleware");
router.post("/", async (req, res) => {...
});
router.post("/login", async (req, res) => {...
});
router.get("/auth", validateTocken, (req, res) => {...
});
// 사용자 정보를 가져오는 router입니다.
router.get("/basicInfo/:id", async (req, res) => {
const id = req.params.id;
// exclude로 password라는 필드 데이터는 가져오지 않겠다는 의미입니다.
const basicInfo = await Users.findByPk(id, {
attributes: { exclude: ["password"] },
});
res.json(basicInfo);
});
module.exports = router;
http://localhost:1234/auth/basicInfo/10이 호출되면 사용자 정보를 가져옵니다.
exclude는 테이블에서 제외하고 싶은 필드를 지정해 줍니다.
📌 사용자가 작성한 글 가져오는 router 생성하기(Posts)
// ./server/routes/Post.js
const express = require("express");
const router = express.Router();
const { Posts, Likes } = require("../models");
const { validateTocken } = require("../middlewares/AuthMiddleware");
// Posts 테이블에 저장된 데이터를 다 가져옵니다.
router.get("/", async (req, res) => {
// Likes를 배열 형식으로 포함해서 데이터를 가져옵니다.
const listOfPosts = await Posts.findAll({ include: [Likes] });
res.json(listOfPosts);
});
router.get("/byId/:id", async (req, res) => {...
});
router.get("/byuserId/:id", async (req, res) => {...
});
router.post("/", validateTocken, async (req, res) => {...
});
module.exports = router;
include는 다른 테이블에서 포함하고 싶은 데이터가 있을 때 사용합니다.
[Likes] 이렇게 하면 해당 데이터를 배열 형태로 가져옵니다.
📌 Profile 화면 생성, route 경로 지정하기
// ./client/src/pages/Home.js
import React from "react";
import axios from "axios";
import { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
function Home() {
const [listOfPosts, setListOfPosts] = useState([]);
let navigate = useNavigate();
useEffect(() => {...
}, []);
const likeAPost = (postId) => {...
};
return (
<div>
{listOfPosts.map((value, key) => {
return (
<div className="posts" key={key}>
<div className="title">{value.title}</div>
<div
className="body"
onClick={() => {
navigate(`/post/${value.id}`);
}}
>
{value.postText}
</div>
<div className="footer">
{/*
UserId를 파라미터로 전달합니다.
*/}
<Link to={`/profile/${value.UserId}`}>
{value.username}
</Link>
<div className="likeContainer">
<button
type="button"
className="likeBtn"
onClick={() => {
likeAPost(value.id);
}}
>
Like
</button>
<label>{value.Likes.length}</label>
</div>
</div>
</div>
);
})}
</div>
);
}
export default Home;
// ./client/src/pages/Profile.js
import React, { useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import axios from "axios";
function Profile() {
let { id } = useParams();
const [username, setUsername] = useState("");
const [listOfPosts, setListOfPosts] = useState([]);
const navigate = useNavigate();
useEffect(() => {
// 사용자 정보를 가져옵니다.(UserId를 전달합니다.)
axios.get(`http://localhost:3001/auth/basicInfo/${id}`).then((respose) => {
setUsername(respose.data.username);
});
// 사용자가 작성한 글을 가져옵니다.(UserId를 전달합니다.)
axios.get(`http://localhost:3001/posts/byuserId/${id}`).then((respose) => {
setListOfPosts(respose.data);
});
}, []);
return (
<div className="profilePageContainer">
<div className="basicInfo">
<h1>Username: {username}</h1>
</div>
<div className="listOfPosts">
{listOfPosts.map((value, key) => {
return (
<div className="posts" key={key}>
<div className="title">{value.title}</div>
<div
className="body"
onClick={() => {
navigate(`/post/${value.id}`);
}}
>
{value.postText}
</div>
<div className="footer">
{value.username}
<div className="likeContainer">
<label>{value.Likes.length}</label>
</div>
</div>
</div>
);
})}
</div>
</div>
);
}
export default Profile;
// ./client/src/App.js
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import Home from "./pages/Home";
import "./App.css";
import CreatePost from "./pages/CreatePost";
import Post from "./pages/Post";
import Login from "./pages/Login";
import Registration from "./pages/Registration";
import Profile from "./pages/Profile";
import { AuthContext } from "./helpers/AuthContext";
import { useEffect, useState } from "react";
import axios from "axios";
function App() {
const [authState, setAuthState] = useState({...
});
useEffect(() => {...
}, []);
const logout = () => {...
};
return (
<div className="App">
<AuthContext.Provider value={{ authState, setAuthState }}>
<BrowserRouter>
<div className="nav">...
</div>
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/createpost" exact element={<CreatePost />} />
<Route path="/post/:id" exact element={<Post />} />
<Route path="/login" exact element={<Login />} />
<Route path="/registration" exact element={<Registration />} />
{/* 사용자 정보를 볼 수 있도록 경로를 지정합니다. */}
<Route path="/profile/:id" exact element={<Profile />} />
</Routes>
</BrowserRouter>
</AuthContext.Provider>
</div>
);
}
export default App;
Home.js 설명
1. Link 태그: App.js에서 지정한 경로로 UserId를 파라미터를 전달합니다.
Profile.js 설명
1. axios.get: Users와 Posts router로 UserId를 파라미터로 전달해서 사용자 이름과 사용자가 작성한 글 목록을 가져옵니다.
App.js 설명
1. <Route path="/profile/:id" exat element={<Profile/>}/>: :id는 전달된 파라미터를 의미합니다. 그리고 해당 경로로 이동하면 Profile.js로 이동합니다.
📌 결과
📌 느낀 점
각각의 테이블에서 id만 연결해 줘도 여러 정보를 가져올 수 있다는 걸 깨달았습니다..!
저는 직접 하나하나 다 넣을 생각을 했는데 덕분에 복잡하지 않게 데이터 스키마를 구현할 수 있을 것 같습니다.😊
다음은 사용자의 비밀번호를 수정하는 방법에 대해 배울 것 같은데 이번엔 제가 할 수 있는 것들은 미리 다 작성한 뒤 강의를 들으면 더 도움 될 것 같아 이런 식으로 공부를 해보려고 합니다.
728x90
'MySQL' 카테고리의 다른 글
axios.post()에서 여러 개 데이터를 보내야 할 때 (0) | 2023.11.18 |
---|---|
React, MySQL 14일차 (글 수정과 비밀번호 변경하기) (0) | 2023.11.05 |
React, MySQL 12일차 (좋아요 누르기) (2) | 2023.10.30 |
React, MySQL 11일차 (로그아웃과 댓글 삭제하기) (0) | 2023.10.28 |
React, MySQL 10일차 (댓글 작성자 화면에 표시하기) (0) | 2023.10.24 |