[React] 5. Blog v1

문정준's avatar
Aug 22, 2025
[React] 5. Blog v1

1. 파일 만들기

notion image
 

필요한 라이브러리

npm install

  • axios
  • react-redux
  • jwt-decode
  • bootstrap
  • react-bootstrap
  • react-bootstrap-icons
  • styled-components
  • react-router-dom
 

2. 페이지 작성

JoinForm

import axios from "axios"; import React, { useState } from "react"; import { Button, Form } from "react-bootstrap"; import { useNavigate } from "react-router-dom"; const JoinForm = (props) => { const navigate = useNavigate(); const [user, setUser] = useState({}); function changeValue(e) {} async function submitJoin(e) { e.preventDefault(); // 새로고침 막기 (action 발동 막기) } return ( <Form> <Form.Group> <Form.Label>Username</Form.Label> <Form.Control type="text" placeholder="Enter username" name="username" onChange={changeValue} /> </Form.Group> <Form.Group> <Form.Label>Password</Form.Label> <Form.Control type="password" placeholder="Enter password" name="password" onChange={changeValue} /> </Form.Group> <Form.Group> <Form.Label>Email</Form.Label> <Form.Control type="email" placeholder="Enter email" name="email" onChange={changeValue} /> </Form.Group> <Button variant="primary" type="submit" onClick={submitJoin}> 회원가입 </Button> </Form> ); }; export default JoinForm;

LoginForm

import axios from "axios"; import React, { useState } from "react"; import { Button, Form } from "react-bootstrap"; import { useDispatch } from "react-redux"; import { useNavigate } from "react-router-dom"; const LoginForm = (props) => { const navigate = useNavigate(); const [user, setUser] = useState({}); async function submitLogin(e) { e.preventDefault(); } const changeValue = (e) => {}; return ( <Form> <Form.Group> <Form.Label>Username</Form.Label> <Form.Control type="text" placeholder="Enter username" name="username" onChange={changeValue} /> </Form.Group> <Form.Group> <Form.Label>Password</Form.Label> <Form.Control type="password" placeholder="Enter password" name="password" onChange={changeValue} /> </Form.Group> <Button variant="primary" type="submit" onClick={submitLogin}> 로그인 </Button> </Form> ); }; export default LoginForm;

Home

import React, { useState } from "react"; import { Form, FormControl, Pagination } from "react-bootstrap"; import BoardItem from "../../components/BoardItem"; const Home = () => { const [page, setPage] = useState(0); const [keyword, setKeyword] = useState(""); const [model, setModel] = useState({}); async function apiHome() {} function changeValue(e) {} return ( <div> <Form className="d-flex mb-4" onSubmit={""}> <FormControl type="search" placeholder="Search" className="me-2" aria-label="Search" value={keyword} onChange={changeValue} /> </Form> <BoardItem key={1} id={1} title={"제목1"} page={0} /> <br /> <div className="d-flex justify-content-center"> <Pagination> <Pagination.Item onClick={""} disabled={false}> Prev </Pagination.Item> <Pagination.Item onClick={""} disabled={false}> Next </Pagination.Item> </Pagination> </div> </div> ); }; export default Home;

Detail

import React, { useState } from "react"; import { Button } from "react-bootstrap"; import { Link, useNavigate } from "react-router-dom"; const Detail = (props) => { const { id } = 1; const navigate = useNavigate(); const [board, setBoard] = useState({}); async function fetchDetail(boardId) {} async function fetchDelete(boardId) {} return ( <div> <Link to={`/update-form/${board.id}`} className="btn btn-warning"> 수정 </Link> <Button className="btn btn-danger" onClick={() => fetchDelete(board.id)}> 삭제 </Button> <br /> <br /> <h1>제목1</h1> <hr /> <div>내용1</div> </div> ); }; export default Detail;

SaveForm

import axios from "axios"; import React, { useState } from "react"; import { Button, Form } from "react-bootstrap"; import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; const SaveForm = (props) => { const navigate = useNavigate(); const [board, setBoard] = useState({}); async function submitPost(e) { e.preventDefault(); } function changeValue(e) {} return ( <div> <h1>글쓰기</h1> <hr /> <Form> <Form.Group> <Form.Label>Title</Form.Label> <Form.Control type="text" placeholder="Enter title" name="title" onChange={changeValue} /> </Form.Group> <Form.Group> <Form.Label>Content</Form.Label> <Form.Control as="textarea" row={5} name="content" onChange={changeValue} /> </Form.Group> <Button variant="primary" type="submit" onClick={submitPost}> 글등록 </Button> </Form> </div> ); }; export default SaveForm;

UpdateForm

import axios from "axios"; import React, { useEffect, useState } from "react"; import { Button, Form } from "react-bootstrap"; import { useSelector } from "react-redux"; import { useNavigate, useParams } from "react-router-dom"; const UpdateForm = (props) => { const { id } = 1; const navigate = useNavigate(); const [board, setBoard] = useState({}); async function updateSubmit(e) { e.preventDefault(); } const changeValue = (e) => {}; async function fetchUserInfo() {} return ( <div> <h1>글수정</h1> <hr /> <Form> <Form.Group> <Form.Label>Title</Form.Label> <Form.Control value={"제목1"} type="text" placeholder="Enter title" name="title" onChange={changeValue} /> </Form.Group> <Form.Group> <Form.Label>Content</Form.Label> <Form.Control as="textarea" row={5} value={"내용1"} name="content" onChange={changeValue} /> </Form.Group> <Button variant="primary" type="submit" onClick={updateSubmit}> 글수정 </Button> </Form> </div> ); }; export default UpdateForm;
 

3. 컴포넌트 작성

BoardItem

import React from "react"; import { Card } from "react-bootstrap"; import { Link } from "react-router-dom"; const BoardItem = (props) => { return ( <Card className="mb-2"> <Card.Body> <Card.Title>제목1</Card.Title> <Link to={"/board/1"} variant="primary" className="btn btn-primary"> 상세보기 </Link> </Card.Body> </Card> ); }; export default BoardItem;

Header

import React from "react"; import { Nav, Navbar } from "react-bootstrap"; import { Link } from "react-router-dom"; function Header(props) { return ( <div> <Navbar bg="dark" expand="lg" variant="dark"> <Link to="/" className="navbar-brand"> 블로그홈 </Link> <Navbar.Toggle aria-controls="basic-navbar-nav" /> <Navbar.Collapse id="basic-navbar-nav"> <Nav className="mr-auto"> <Link to="/save-form" className="nav-link"> 글쓰기 </Link> <Link className="nav-link" onClick={""}> 로그아웃 </Link> <Link to="/login-form" className="nav-link"> 로그인 </Link> <Link to="/join-form" className="nav-link"> 회원가입 </Link> </Nav> </Navbar.Collapse> </Navbar> <br /> </div> ); } export default Header;
 
notion image
notion image
 
notion image
notion image
 
 
notion image
notion image
 
Share article

sxias