배포되는 파일들
- App.css
- Index.template.tsx
- mussg.svg
라이브러리 설치
- react-router-dom
- @tanstack/react-query
- styled-components
- open-color
index 페이지 구현
App.tsx
import React from 'react';
import { RouterProvider } from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { router } from "./router";
import "./App.css";
const queryClient = new QueryClient({
// ...
});
export const App: React.FC = () => {
return (
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
);
};
router.tsx
import { Route, createBrowserRouter, createRoutesFromElements } from "react-router-dom";
import { IndexPage } from "./pages/Index";
export const router = createBrowserRouter(
createRoutesFromElements(
<Route index Component={IndexPage} />
)
};
index.template.tsx
import { Link } from "react-router-dom";
import { styled } from "styled-components";
import oc from "open-color";
import { ReactComponent as MussgImage } from "@/assets/mussg.svg";
export const IndexTemplate: React.FC = () => {
return (
<Container>
<MussgImage height="182" />
<AppTitle>Programmers Note Editor</AppTitle>
<AppDescription>
<strong>Programmers Note Editor</strong>
<br />
메모는 클라우드에 저장되어 언제 어디서나 사용할 수 있습니다.
</AppDescription>
<StartLink to="login">무료로 시작하기</StartLink>
<Footer>© 2023 Grepp Co.</Footer>
</Container>
);
};
index.tsx
import { IndexTemplate } from "./Index.template";
export const IndexPage = () => {
return <IndexTemplate />;
}
회원가입 페이지 구현
pages/Join.tsx
import { useNavigate } from "react-router-dom";
import { useJoin } from "@/hooks/useJoin";
import { JoinTemplate, JoinTemplateProps } from "./Join.template";
export const JoinPage = () => {
const navigate = useNavigate();
const { join } = useJoin();
const handleSubmit: JoinTemplateProps["onSubmit"] = async ({ email, password }) => {
const { result } = await join({ email, password });
if (result === "conflict") {
return alert("이미 가입된 이메일입니다.");
}
result satisfies "success";
alert("회원가입이 완료되었습니다.");
navigate("/login");
};
return <JoinTemplate onSubmit={handleSubmit} />;
}
components/JoinForm.tsx
import React from "react";
export interface JoinFormProps {
onSubmit?(e: { email: string; password: string }): void;
}
export const JoinForm: React.FC<JoinFormProps> = (props) => {
return (
<Container>
<Title>회원가입</Title>
<Form
method="post"
onSubmit={(e) => {
e.preventDefault();
// ...
if (password !== passwordConfirm) {
// ...
}
props.onSubmit?.({ email, password });
}}
>
<InputContainer>
// ...
</InputContainer>
// ...
</Container>
);
};
hooks/useJoin.tsx
export const useJoin = () => {
const queryClient = useQueryClient();
const joinMutation = ...
mutationFn: async (params: JoinParams) => {
const [error] = await ...(requestJoin(params));
if (isAxiosError(error) && error.response?.status === 409) {
return { result: "conflict" as const };
}
if (error) {
throw error;
}
return { result: "success" as const };
},
onSuccess: async () => {
// ...
},
});
return { join: joinMutation.mutateAsync };
};
apis/requrestJoin.tsx
import { httpClient } from "@/utils/http";
export interface JoinParams {
email: string;
password: string;
}
export async function requestJoin(params: JoinParams) {
await httpClient.post("/users", params);
}
'데브코스' 카테고리의 다른 글
[20주차 - DAY1] 웹 기반 문서 편집기 제작 프로젝트(5) (0) | 2024.07.08 |
---|---|
[19주차 - DAY5] 웹 기반 문서 편집기 제작 프로젝트(4) (0) | 2024.07.05 |
[19주차 - DAY3] 웹 기반 문서 편집기 제작 프로젝트(2) (0) | 2024.07.03 |
[19주차 - DAY2] 웹 기반 문서 편집기 제작 프로젝트(1) (0) | 2024.06.28 |
[18주차 - DAY5] 오픈소스 기여(4) (0) | 2024.06.28 |