React에서 사용자 정의 캘린더 구성 요소를 구축하는 방법
41821 단어 typescriptjavascriptcssreact
소개
많은 웹 애플리케이션은 달력을 사용하여 날짜를 관리해야 하지만 대다수의 기사/튜토리얼은 항상 타사 라이브러리를 사용합니다. 그것이 나쁘다는 것이 아니라 반대로 응용 프로그램의 프로토타입을 만드는 데 많은 도움이 되지만 디자인과 요구 사항이 맞춤형인 경우 개발자에게 매우 어렵습니다.
같은 이유로 오늘 기사에서는 나중에 확장하여 더 많은 기능을 추가할 수 있는 기본 구성 요소를 만드는 방법을 알려 드리겠습니다.
우리는 무엇을 사용할 것입니까?
오늘은 제가 가장 좋아하는 두 가지 라이브러리를 사용할 것입니다.
Day.js - 날짜를 조작, 구문 분석 및 검증하는 데 도움이 되는 라이브러리입니다
Stitches - 경이로운 개발 경험이 있는 css-in-js 스타일링 라이브러리
이들은 이 문서에서 사용된 라이브러리이지만 동일한 결과를 다른 라이브러리에서도 쉽게 복제할 수 있다는 점을 명심하십시오.
전제 조건
이 자습서를 따르려면 다음이 필요합니다.
TypeScript에 익숙하지 않더라도 데이터 유형을 "무시"하고 코드가 JavaScript와 정확히 동일하기 때문에 괜찮습니다.
시작하기
첫 번째 단계로 프로젝트 디렉토리를 생성하고 해당 디렉토리로 이동합니다.
yarn create vite react-calendar-ts --template react-ts
cd react-calendar-ts
이제 필요한 종속성을 설치할 수 있습니다.
yarn add dayjs react-icons @stitches/react @fontsource/anek-telugu
그런 다음
styles.ts
라는 파일에 html 요소의 스타일을 만듭니다.// @/src/styles.ts
import { styled } from "@stitches/react";
export const MainWrapper = styled("div", {
width: 240,
borderRadius: 10,
padding: 20,
backgroundColor: "white",
boxShadow: "-6px 7px 54px -24px rgba(0,0,0,0.5)",
fontFamily: "Anek Telugu",
});
export const CalendarHeaderWrapper = styled("div", {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
});
export const WeekDaysWrapper = styled("div", {
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
});
export const WeekDayCell = styled("div", {
height: 30,
width: 30,
margin: 2,
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "#9BA4B4",
});
export const CalendarContentWrapper = styled("div", {
display: "flex",
flexDirection: "row",
});
export const CalendarDayCell = styled("div", {
height: 30,
width: 30,
display: 'flex',
alignItems: "center",
justifyContent: "center",
borderRadius: 6,
margin: 2,
variants: {
variant: {
default: {
color: "#1B1B2F",
},
today: {
color: "#E43F5A",
},
nextMonth: {
color: "#DAE1E7",
},
},
},
});
생성된 요소의 스타일과 오늘의 변형이 이미 추가되었으므로 이제 오늘 기사의 모든 논리를 포함할
App.tsx
구성 요소 작업을 시작할 수 있습니다.// @/src/App.tsx
import "@fontsource/anek-telugu";
import { useCallback, useMemo, useState } from "react";
import dayjs, { Dayjs } from "dayjs";
import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from "react-icons/md";
import * as Styles from "./styles";
export const App = () => {
// logic goes here...
return (
// JSX goes here...
)
}
위의 코드에서 우리는 구성 요소를 만드는 데 필요한 가져오기를 수행했습니다. 다음 단계는 현재 날짜, 월 1일, 월 1일의 1일이 무엇인지 세 가지 중요한 값을 획득하는 것입니다.
// @/src/App.tsx
import "@fontsource/anek-telugu";
import { useCallback, useMemo, useState } from "react";
import dayjs, { Dayjs } from "dayjs";
import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from "react-icons/md";
import * as Styles from "./styles";
export const App = () => {
const [selectedDate, setSelectedDate] = useState<Dayjs>(dayjs());
const currentDay = useMemo(() => dayjs().toDate(), []);
const firstDayOfTheMonth = useMemo(
() => selectedDate.clone().startOf("month"),
[selectedDate]
);
const firstDayOfFirstWeekOfMonth = useMemo(
() => dayjs(firstDayOfTheMonth).startOf("week"),
[firstDayOfTheMonth]
);
// more logic goes here...
return (
// JSX goes here...
)
}
이 세 가지 날짜를 얻었으므로 이제 두 개의 함수를 만들어야 합니다. 하나는 매월 첫 번째 날을 생성하는 함수이고 두 번째 함수는 첫 번째 요일을 고려하여 해당 월의 주를 생성하는 역할을 합니다. .
// @/src/App.tsx
import "@fontsource/anek-telugu";
import { useCallback, useMemo, useState } from "react";
import dayjs, { Dayjs } from "dayjs";
import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from "react-icons/md";
import * as Styles from "./styles";
export const App = () => {
const [selectedDate, setSelectedDate] = useState<Dayjs>(dayjs());
const currentDay = useMemo(() => dayjs().toDate(), []);
const firstDayOfTheMonth = useMemo(
() => selectedDate.clone().startOf("month"),
[selectedDate]
);
const firstDayOfFirstWeekOfMonth = useMemo(
() => dayjs(firstDayOfTheMonth).startOf("week"),
[firstDayOfTheMonth]
);
const generateFirstDayOfEachWeek = useCallback((day: Dayjs): Dayjs[] => {
const dates: Dayjs[] = [day];
for (let i = 1; i < 6; i++) {
const date = day.clone().add(i, "week");
dates.push(date);
}
return dates;
}, []);
const generateWeek = useCallback((day: Dayjs): Date[] => {
const dates: Date[] = [];
for (let i = 0; i < 7; i++) {
const date = day.clone().add(i, "day").toDate();
dates.push(date);
}
return dates;
}, []);
// more logic goes here...
return (
// JSX goes here...
)
}
이제 필요한 날짜와 해당 월의 주를 생성하는 데 필요한 기능이 있으므로 이제
useMemo()
후크를 사용하여 위에서 언급한 날짜의 변경 사항에 반응하고 해당 월의 일과 주를 생성해야 합니다. 다음과 같이 동일한 내용을 메모합니다.// @/src/App.tsx
import "@fontsource/anek-telugu";
import { useCallback, useMemo, useState } from "react";
import dayjs, { Dayjs } from "dayjs";
import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from "react-icons/md";
import * as Styles from "./styles";
export const App = () => {
const [selectedDate, setSelectedDate] = useState<Dayjs>(dayjs());
const currentDay = useMemo(() => dayjs().toDate(), []);
const firstDayOfTheMonth = useMemo(
() => selectedDate.clone().startOf("month"),
[selectedDate]
);
const firstDayOfFirstWeekOfMonth = useMemo(
() => dayjs(firstDayOfTheMonth).startOf("week"),
[firstDayOfTheMonth]
);
const generateFirstDayOfEachWeek = useCallback((day: Dayjs): Dayjs[] => {
const dates: Dayjs[] = [day];
for (let i = 1; i < 6; i++) {
const date = day.clone().add(i, "week");
dates.push(date);
}
return dates;
}, []);
const generateWeek = useCallback((day: Dayjs): Date[] => {
const dates: Date[] = [];
for (let i = 0; i < 7; i++) {
const date = day.clone().add(i, "day").toDate();
dates.push(date);
}
return dates;
}, []);
const generateWeeksOfTheMonth = useMemo((): Date[][] => {
const firstDayOfEachWeek = generateFirstDayOfEachWeek(
firstDayOfFirstWeekOfMonth
);
return firstDayOfEachWeek.map((date) => generateWeek(date));
}, [generateFirstDayOfEachWeek, firstDayOfFirstWeekOfMonth, generateWeek]);
return (
// JSX goes here...
)
}
로직이 완료되면
generateWeeksOfTheMonth
변수에서 얻은 데이터를 매핑하기만 하면 되지만 월 사이를 탐색하고 선택한 날짜를 업데이트해야 한다는 점도 고려해야 합니다. 달력에서 현재 날짜를 시각적으로 식별해야 하는 것과 같습니다. 다음과 같이 할 수 있습니다.// @/src/App.tsx
import "@fontsource/anek-telugu";
import { useCallback, useMemo, useState } from "react";
import dayjs, { Dayjs } from "dayjs";
import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from "react-icons/md";
import * as Styles from "./styles";
export const App = () => {
// hidden for simplicity...
return (
<Styles.MainWrapper>
<Styles.CalendarHeaderWrapper>
<h3>{selectedDate.clone().format("MMM YYYY")}</h3>
<div>
<MdKeyboardArrowLeft
size={25}
onClick={() => setSelectedDate((date) => date.subtract(1, "month"))}
/>
<MdKeyboardArrowRight
size={25}
onClick={() => setSelectedDate((date) => date.add(1, "month"))}
/>
</div>
</Styles.CalendarHeaderWrapper>
<Styles.WeekDaysWrapper>
{generateWeeksOfTheMonth[0].map((day, index) => (
<Styles.WeekDayCell key={`week-day-${index}`}>
{dayjs(day).format("dd")}
</Styles.WeekDayCell>
))}
</Styles.WeekDaysWrapper>
{generateWeeksOfTheMonth.map((week, weekIndex) => (
<Styles.CalendarContentWrapper key={`week-${weekIndex}`}>
{week.map((day, dayIndex) => (
<Styles.CalendarDayCell
key={`day-${dayIndex}`}
variant={
selectedDate.clone().toDate().getMonth() !== day.getMonth()
? "nextMonth"
: dayjs(currentDay).isSame(day, "date")
? "today"
: "default"
}
>
{day.getDate()}
</Styles.CalendarDayCell>
))}
</Styles.CalendarContentWrapper>
))}
</Styles.MainWrapper>
)
}
지금까지 기사를 따라했다면 브라우저에서 다음과 매우 유사한 결과를 얻을 수 있을 것입니다.
다음 과제는 무엇입니까?
이 점은 상당히 상대적이지만 다음 기능에 중점을 둘 것입니다.
결론
늘 그렇듯이 기사가 마음에 드셨기를 바라며 기존 프로젝트에 도움이 되었거나 단순히 사용해 보고 싶으셨기를 바랍니다.
기사에서 잘못된 부분을 발견했다면 댓글로 알려주시면 수정하겠습니다. 마치기 전에 이 기사의 소스 코드에 액세스하려면 github 저장소에 대한 링크here를 남겨둡니다.
Reference
이 문제에 관하여(React에서 사용자 정의 캘린더 구성 요소를 구축하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/franciscomendes10866/how-to-build-a-custom-calendar-component-in-react-26kj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)