- 간략히 작성한 화면설계서를 참고해서 게시판을 만들 예정.


- App.js
import './App.css';
import BoardHome from './component/BoardHome';
function App() {
return (
<div className="App">
<BoardHome />
</div>
);
}
export default App;
- BoardHome.jsx
import React from 'react';
import { BrowserRouter, Route, Routes } from "react-router-dom";
import BoardList from './BoardList';
import BoardDetail from './BoardDetail';
import BoardWrite from './BoardWrite';
import BoardModify from './BoardModify';
const BoardHome = () => {
return (
<div className='boardHome'>
<h1>My First React Board Project</h1>
<hr />
<BrowserRouter>
<Routes>
<Route path='/' element={<BoardList />} />
<Route path='/list' element={<BoardList />} />
<Route path="/detail/:id" element={<BoardDetail />} />
<Route path='/write' element={<BoardWrite />} />
<Route path="/modify/:id" element={<BoardModify />} />
</Routes>
</BrowserRouter>
</div>
);
};
export default BoardHome;
- BoardList.jsx
import React from 'react';
import { boardList } from '../data/data';
import './BoardList.css';
import {Link} from 'react-router-dom';
const BoardList = () => {
return (
<div className='boardList'>
<h2>Board List Page</h2>
<table>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
</tr>
</thead>
<tbody>
{boardList.map(l => (
<tr key={l.id}>
<td>{l.id}</td>
<td>
<Link to={`/detail/${l.id}`}>{l.title}</Link>
</td>
<td>{l.writer}</td>
<td>{l.reg_date.substring(0, l.reg_date.indexOf("T"))}</td>
</tr>
))}
</tbody>
</table>
<div className='mg-top-20'>
<Link to={`/write`}><button>글쓰기</button></Link>
</div>
</div>
);
};
export default BoardList;
- BoardDetail.jsx
import React from 'react';
import { boardList } from '../data/data';
import { useParams, Link } from 'react-router-dom';
import './BoardList.css';
const BoardDetail = () => {
const { id } = useParams();
//특정 조건을 만족하는 요소의 index를 찾는 함수(findIndex())
//boardList.findIndex(l => l.id === Number(id));
//params는 String 으로 값을 가져옴 ==> 따라서 Number로 형변환
//굳이 findIndex를 사용하는 이유 : id의 값과 index(boardList의 index)가 맞지 않기 때문.
const idx = boardList.findIndex(l => l.id === Number(id));
console.log(idx);
const board=boardList[idx];
console.log(board);
return (
<div className='boardDetail'>
<h2>No.{board.id} / Board Detail Page</h2>
<div className='btns'>
<Link to={`/modify/${board.id}`}><button>Modify</button></Link>
<button>Remove</button>
<Link to={`/`}><button>List</button></Link>
</div>
<div className='contents'>
<h3>{board.title}</h3>
<div className='writer'>{board.writer} [{board.reg_date.substring(0, board.reg_date.indexOf("T"))}]</div>
<div className='con'>{board.contents}</div>
</div>
</div>
);
};
export default BoardDetail;
- BoardWrite.jsx
import React, { useRef, useState } from 'react';
import './BoardList.css';
import { Link } from 'react-router-dom';
import { boardList } from '../data/data';
const BoardWrite = () => {
const nextId = useRef(8);
//오늘 날짜 가져오기
const today = new Date();
//날짜 포맷 생성
const formattedDate = `${today.getFullYear()}-${(today.getMonth() + 1)}-${today.getDate()}`
const [ boardListTmp, setBoardListTmp] = useState([...boardList]);
const [board, setBoard] = useState({
title: '',
writer: '',
contents: '',
reg_date: formattedDate,
});
const { title, writer, contents, reg_date } = board;
const onChange = (e) => {
const { name, value } = e.target;
setBoard({
...board,
[name]:value
});
}
const onCreate = ()=>{
const b = {
id: nextId.current,
title: title,
writer: writer,
contents: contents
};
setBoardListTmp(boardListTmp.concat(b));
setBoard({
title:'',
writer:'',
contents:'',
reg_date: formattedDate
});
nextId.current += 1;
}
return (
<div className='boardWrite'>
<h2>Board Write Page</h2>
<form action="" className='contents'>
<div className='wrtCon'>
<input type="text" value={reg_date} readOnly className='readonly-input' />
<input type="text" name='title' value={title} placeholder='Title...' className='input-field' onChange={onChange} />
<input type="text" name='writer' value={writer} placeholder='Writer...' className='input-field' onChange={onChange} />
<textarea name='contents' value={contents} placeholder='Contents...' className='textarea-field' onChange={onChange} />
</div>
<div className='btns'>
<Link to={`/`}>
<button onClick={onCreate}>Submit</button>
</Link>
<Link to={`/`}><button>List</button></Link>
</div>
</form>
</div>
);
};
export default BoardWrite;
- BoardModify.jsx
import React, { useState, useEffect} from 'react';
import { boardList } from '../data/data';
import { Link, useParams } from 'react-router-dom';
const BoardModify = () => {
const { id } = useParams();
const [boardListTmp, setBoardListTmp] = useState([...boardList]);
const [board, setBoard] = useState({
title: '',
writer: '',
contents: '',
reg_date: '',
});
const { title, writer, contents, reg_date } = board;
useEffect(() => {
const boardId = Number(id);
setBoard(boardListTmp.find(l => l.id === boardId))
}, [id, boardListTmp]);
const onChange = (e) => {
const { name, value } = e.target;
setBoard({
...board,
[name]:value
});
}
const onUpdate = ()=>{
const updatedList = boardListTmp.map(post =>
post.id === Number(id) ? { ...board, reg_date } : post
);
setBoardListTmp(updatedList);
}
return (
<div className='boardModify'>
<h2>Board Write Page</h2>
<form action="" className='contents'>
<div className='wrtCon'>
<input type="text" value={reg_date.substring(0, reg_date.indexOf("T"))} readOnly className='readonly-input' />
<input type="text" name='title' value={title} placeholder='Title...' className='input-field' onChange={onChange} />
<input type="text" name='writer' value={writer} placeholder='Writer...' className='input-field' onChange={onChange} />
<textarea name='contents' value={contents} placeholder='Content...' className='textarea-field' onChange={onChange} />
</div>
<div className='btns'>
<Link to={`/`}>
<button onClick={onUpdate}>Submit</button>
</Link>
<Link to={`/`}><button>List</button></Link>
</div>
</form>
</div>
);
};
export default BoardModify;
- Data.js
export const boardList =
[
{
"id": 7,
"title": "React란 무엇인가요?",
"contents": "React는 몇 가지 종류의 컴포넌트를 가지지만 우리는 React.Component의 하위 클래스를 사용해보겠습니다. 리액트는 사용자 인터페이스를 구축하기 위한 JavaScript 라이브러리로, 페이스북에서 개발하였습니다. 리액트는 컴포넌트 기반 아키텍처를 사용하여 UI를 재사용 가능한 독립적인 컴포넌트로 나누어 관리합니다. 이를 통해 개발자는 코드의 효율성과 유지 보수성을 높일 수 있으며, 상태(state)와 속성(props)을 활용하여 데이터 흐름을 관리합니다. JSX라는 문법을 사용하여 JavaScript 코드 안에 HTML과 유사한 코드를 작성할 수 있으며, 이는 가독성을 높여줍니다. 리액트는 또한 가상 DOM을 사용하여 실제 DOM 조작을 최적화하고 성능을 향상시킵니다. 이러한 특성 덕분에 리액트는 대규모 애플리케이션과 복잡한 사용자 인터페이스를 효율적으로 개발하는 데 적합합니다.",
"writer": "purple",
"reg_date": "2024-05-25T07:41:21.000Z"
},
{
"id": 6,
"title": "브라우저에 코드 작성하기",
"contents": "먼저 새 탭에서 초기 코드를 열어주세요. 새 탭은 비어있는 틱택토 게임판과 React 코드를 보여줄 것입니다. 우리는 자습서에서 React 코드를 편집할 것입니다. 브라우저에 코드 작성하기 위해 먼저 HTML 파일을 생성한 후, <script> 태그를 사용하여 JavaScript 코드를 작성합니다. 코드 작성 후 브라우저에서 파일을 열면 결과를 확인할 수 있습니다. 간단한 예로, <script> 태그 안에 console.log(\"Hello, World!\")를 입력하고, 개발자 도구의 콘솔에서 결과를 확인할 수 있습니다. 또한, 온라인 코드 편집기나 IDE를 이용해 작성한 코드를 실시간으로 테스트하고 결과를 확인하는 방법도 있습니다. 이를 통해 코드의 기능을 검증하고 디버깅할 수 있습니다.",
"writer": "navy",
"reg_date": "2024-05-25T07:41:20.000Z"
},
{
"id": 5,
"title": "자습서를 시작하기 전에",
"contents": "우리는 이 자습서에서 작은 게임을 만들겁니다. 게임을 만들고 싶지 않아서 자습서를 건너뛰고 싶을 수 있습니다. 그래도 한번 해보세요! 리액트를 시작하기 전에, 기본적인 HTML, CSS, JavaScript에 대한 이해가 필요합니다. HTML은 웹 페이지의 구조를 만들고, CSS는 그 스타일을 정의하며, JavaScript는 동적인 기능을 추가합니다. 이러한 기초 지식이 탄탄하면 리액트를 더 쉽게 배우고 활용할 수 있습니다. 리액트는 컴포넌트 기반의 라이브러리로, UI를 재사용 가능한 컴포넌트로 구성합니다. 이를 통해 코드의 효율성과 가독성을 높일 수 있습니다. 리액트를 배우면서 JSX 문법을 접하게 될 텐데, 이는 JavaScript와 HTML을 결합한 형태로, 컴포넌트를 작성하는 데 매우 유용합니다. 리액트의 상태 관리와 props의 개념도 중요합니다. 상태(state)는 컴포넌트의 데이터이며, props는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 방법입니다. 이러한 기본 개념을 이해한 후, 리액트의 생명주기, 훅(hook) 사용법, 라우팅 등으로 점진적으로 깊이 있는 내용을 학습해 나갈 수 있습니다.리액트를 배우는 가장 좋은 방법은 간단한 프로젝트를 만들어 보는 것입니다. 이를 통해 실제로 코드 작성과 디버깅을 경험하며, 리액트의 장점과 활용 방법을 체감할 수 있습니다. 온라인 자원이나 튜토리얼을 참고하면서 꾸준히 연습하면, 더 빠르게 숙련될 수 있습니다.",
"writer": "blue",
"reg_date": "2024-05-25T07:41:20.000Z"
},
{
"id": 4,
"title": "외부 플러그인을 사용하는 컴포넌트",
"contents": "React는 유연하며 다른 라이브러리나 프레임워크를 함께 활용할 수 있습니다. 이 예제에서는 외부 마크다운 라이브러리인 remarkable을 사용해 \u003Ctextarea\u003E의 값을 실시간으로 변환합니다. 외부 플러그인을 사용하는 컴포넌트는 React 애플리케이션에서 다른 라이브러리나 패키지를 활용하여 기능을 확장하는 방법이다. 예를 들어, Chart.js를 사용하여 데이터 시각화를 구현하거나, React Router를 통해 페이지 간 이동을 관리할 수 있다. 이러한 플러그인은 npm이나 yarn을 통해 설치한 후, 해당 컴포넌트에서 import하여 사용할 수 있다. 컴포넌트 내에서 플러그인 API를 호출하거나 설정 옵션을 전달하여 원하는 기능을 구현하고, props를 통해 부모 컴포넌트로부터 데이터를 전달받아 동적으로 작동하도록 만들 수 있다. 이를 통해 사용자 경험을 향상시키고 개발 시간을 단축할 수 있다.",
"writer": "green",
"reg_date": "2024-05-25T07:41:19.000Z"
},
{
"id": 3,
"title": "애플리케이션",
"contents": "props와 state를 사용해서 간단한 Todo 애플리케이션을 만들 수 있습니다. props와 state를 사용해서 간단한 Todo 애플리케이션을 만들 수 있습니다. 먼저 App 컴포넌트를 생성하여 상태를 관리하고 Todo 리스트와 입력 필드를 포함합니다. TodoList 컴포넌트는 Todo 항목을 렌더링하며, props를 통해 Todo 항목들을 전달받습니다. 각 Todo 항목은 TodoItem 컴포넌트로 나타내며, 여기서 삭제 버튼을 클릭할 때 onDelete 함수를 호출하여 항목을 삭제할 수 있습니다. 이 방식으로 React의 props와 state를 활용하여 간단한 Todo 애플리케이션을 구현할 수 있습니다.",
"writer": "yellow",
"reg_date": "2024-05-25T07:41:19.000Z"
},
{
"id": 2,
"title": "상태를 가지는 컴포넌트",
"contents": "컴포넌트는 this.props를 이용해 입력 데이터를 다루는 것 외에도 내부적인 상태 데이터를 가질 수 있습니다. 이는 this.state로 접근할 수 있습니다. 컴포넌트는 this.props를 이용해 입력 데이터를 다루는 것 외에도 내부적인 상태 데이터를 가질 수 있습니다. 이는 this.state로 접근할 수 있습니다. state는 컴포넌트의 동적인 데이터를 저장하고 관리하는 데 사용되며, 상태가 변경되면 컴포넌트는 자동으로 리렌더링됩니다. 따라서 state를 사용하면 사용자와의 상호작용에 따라 UI를 동적으로 업데이트할 수 있습니다. 이를 통해 React 애플리케이션은 더 나은 사용자 경험을 제공할 수 있습니다.",
"writer": "orange",
"reg_date": "2024-05-25T07:41:19.000Z"
},
{
"id": 1,
"title": "한 번 배워서 어디서나 사용하기",
"contents": "기술 스택의 나머지 부분에는 관여하지 않기 때문에, 기존 코드를 다시 작성하지 않고도 React의 새로운 기능을 이용해 개발할 수 있습니다. 한 번 배워서 어디서나 사용하기 때문에 React는 컴포넌트 기반 아키텍처를 가지고 있어 재사용성이 뛰어납니다. 즉, 한 번 작성한 컴포넌트는 여러 곳에서 활용할 수 있어 코드의 중복을 줄이고 유지보수를 용이하게 합니다. 이러한 특성 덕분에 개발자는 효율적으로 프로젝트를 관리할 수 있으며, 팀원 간의 협업도 수월해집니다. 또한 React의 생태계는 풍부하여 다양한 라이브러리와 도구를 활용할 수 있어, 필요한 기능을 쉽게 통합할 수 있습니다. 결과적으로 React는 유연성과 확장성을 갖춘 현대적인 웹 애플리케이션 개발에 최적화된 선택이 됩니다.",
"writer": "red",
"reg_date": "2024-05-25T07:41:17.000Z"
}
]
- 결과

'프론트엔드 > React' 카테고리의 다른 글
| React로 게시판 만들기(3) (1) | 2024.09.24 |
|---|---|
| React로 게시판 만들기(2) (1) | 2024.09.20 |
| useReducer로 상태 관리 (0) | 2024.09.19 |
| Axios와 useEffect를 사용하여 데이터 가져오기 (0) | 2024.09.09 |
| TODO LIST 만들기 및 useMemo() 개념 (1) | 2024.09.09 |