Home Page 구현하기
UI 구현하기
- 컴포넌트 구조는
- Header 컴포넌트
- DiaryList 컴포넌트
Home.jsx
import Header from "../components/Header";
import Button from "../components/Button";
import DiaryList from "../components/DiaryList";
const Home = () => {
return (
<div>
<Header
title={"2024년 10월"}
leftChild={<Button text="<" />}
rightChild={<Button text=">" />}
/>
<DiaryList />
</div>
);
};
export default Home;
DiaryList.jsx
import Button from "./Button";
import "./DiaryList.css";
import DiaryItem from "./DiaryItem";
const DiaryList = () => {
return (
<div className="DiaryList">
<div className="menu_bar">
<select>
<option value={"latest"}>최신순</option>
<option value={"oldest"}>오래된순</option>
</select>
<Button text={"새 일기 쓰기"} type={"POSITIVE"} />
</div>
<div className="list_wrapper">
<DiaryItem />
</div>
</div>
);
};
export default DiaryList;
DiaryItem.jsx
import { getEmotionImage } from "../utill/get-emotion-image";
import Button from "./Button";
import "./DiaryItem.css";
const DiaryItem = () => {
const emotionId = 4; // 임의값
return (
<div className="DiaryItem">
<div className={`img_section img_section_${emotionId}`}>
<img src={getEmotionImage(emotionId)} />
</div>
<div className="info_section">
<div className="created_date">{new Date().toLocaleDateString()}</div>
<div className="content">일기 컨텐츠</div>
</div>
<div className="button_section">
<Button text={"수정하기"} />
</div>
</div>
);
};
export default DiaryItem;
- css는 너무 길어서 일단 생략
- DiaryList 는 메뉴바 / 리스트 항목으로 나누고, 리스트는 DiaryItem 컴포넌트로 추가한다.
기능 구현하기
Home.jsx
import { useState, useContext } from "react";
import { DiaryStateContext } from "../App";
import Header from "../components/Header";
import Button from "../components/Button";
import DiaryList from "../components/DiaryList";
// 로직이 복잡한 함수일 때 파라미터만으로 필요한 데이터를 다 받을 수 있다면
// 컴포넌트 밖에 생성해도 좋다. 불필요한 리렌더링도 하지 않고, 가독성도 좋다.
const getMonthlyData = (pivotDate, data) => {
const beginTime = new Date(
pivotDate.getFullYear(),
pivotDate.getMonth(),
1,
0,
0,
0
).getTime();
const endTime = new Date(
pivotDate.getFullYear(),
pivotDate.getMonth() + 1,
0,
23,
59,
59
).getTime();
return data.filter(
(item) => beginTime <= item.createdDate && item.createdDate <= endTime
);
};
const Home = () => {
const data = useContext(DiaryStateContext);
const [pivotDate, setPivotDate] = useState(new Date());
const monthlyData = getMonthlyData(pivotDate, data);
const onIncreaseMonth = () => {
setPivotDate(new Date(pivotDate.getFullYear(), pivotDate.getMonth() + 1));
};
const onDecreaseMonth = () => {
setPivotDate(new Date(pivotDate.getFullYear(), pivotDate.getMonth() - 1));
};
return (
<div>
<Header
title={`${pivotDate.getFullYear()}년 ${pivotDate.getMonth() + 1}월`}
leftChild={<Button text="<" onClick={onDecreaseMonth} />}
rightChild={<Button text=">" onClick={onIncreaseMonth} />}
/>
<DiaryList data={monthlyData} />
</div>
);
};
export default Home;
- getMonthlyData - Header 의 < > 버튼 클릭했을 때 달이 넘어가는 기능
DiaryList.jsx
import Button from "./Button";
import "./DiaryList.css";
import DiaryItem from "./DiaryItem";
import { useNavigate } from "react-router-dom";
import { useState } from "react";
const DiaryList = ({ data }) => {
const nav = useNavigate();
const [sortType, setSortType] = useState("latest");
const onChangeSortType = (e) => {
setSortType(e.target.value);
};
const getSortedDate = () => {
return data.toSorted((a, b) => {
if (sortType === "oldest") {
return Number(a.createdDate) - Number(b.createdDate);
} else {
return Number(b.createdDate) - Number(a.createdDate);
}
});
};
const sortedData = getSortedDate();
return (
<div className="DiaryList">
<div className="menu_bar">
<select onChange={onChangeSortType}>
<option value={"latest"}>최신순</option>
<option value={"oldest"}>오래된순</option>
</select>
<Button
text={"새 일기 쓰기"}
type={"POSITIVE"}
onClick={() => nav("/new")}
/>
</div>
<div className="list_wrapper">
{sortedData.map((item) => (
<DiaryItem key={item.id} {...item} />
))}
</div>
</div>
);
};
export default DiaryList;
- getSortedDate 최신순 / 오래된순 정렬
- useNavigate 활용해 페이지 이동
DiaryItem.jsx
import { getEmotionImage } from "../utill/get-emotion-image";
import Button from "./Button";
import "./DiaryItem.css";
import { useNavigate } from "react-router-dom";
const DiaryItem = ({ id, emotionId, createdDate, content }) => {
const nav = useNavigate();
return (
<div className="DiaryItem">
<div
onClick={() => nav(`/diary/${id}`)}
className={`img_section img_section_${emotionId}`}
>
<img src={getEmotionImage(emotionId)} />
</div>
<div onClick={() => nav(`/diary/${id}`)} className="info_section">
<div className="created_date">
{new Date(createdDate).toLocaleDateString()}
</div>
<div className="content">{content}</div>
</div>
<div className="button_section">
<Button onClick={() => nav(`/edit/${id}`)} text={"수정하기"} />
</div>
</div>
);
};
export default DiaryItem;
- 완성
출처 : 한입 크기로 잘라먹는 리액트
'Language > React.js' 카테고리의 다른 글
[React] 감정일기장 프로젝트 : EditPage 구현하기 (0) | 2024.10.29 |
---|---|
[React] 감정일기장 프로젝트 : NewPage 구현하기 (0) | 2024.10.24 |
[React] 감정일기장 프로젝트 : 일기 관리 기능 구현하기 (0) | 2024.10.23 |
[React] 감정일기장 프로젝트 : 공통 컴포넌트 구현하기 (0) | 2024.10.23 |
[React] 감정일기장 프로젝트 : 폰트, 이미지, 레이아웃 설정 (0) | 2024.10.22 |