새 프로젝트를 시작한다.
App.css 안의 내용 다 지워주고 index.css는 삭제한다.
App.jsx 도 정리한다.
그 다음 디팬던시추가
폴더 생성 후 파일을 생성한다.
Layout.jsx
import React from "react";
import { Outlet } from "react-router-dom";
const Layout = () => {
return (
<>
<h2>레이아웃</h2>
<Outlet />
</>
);
};
export default Layout;
CreateUser.jsx
Home.jsx
Login.jsx
Profile.jsx
App.jsx
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import "./App.css";
import Layout from "./components/Layout";
import Home from "./routes/Home";
import Profile from "./routes/Profile";
import Login from "./routes/Login";
import CreateUser from "./routes/CreateUser";
const router = createBrowserRouter([
{
path: "/",
element: <Layout />,
children: [
{
path: "",
element: <Home />,
},
{
path: "/profile",
element: <Profile />,
},
],
},
{
path: "/login",
element: <Login />,
},
{
path: "/create-user",
element: <CreateUser />,
},
]);
function App() {
return (
<>
<RouterProvider router={router} />
</>
);
}
export default App;
라우터를 위의 방법으로도 사용이 가능하다.
path가 기본주소일 때 layout컴포넌트가 들어감
테스트 해보기
로그인과 CreateUser은 레이아웃이 생성되지 않는다.
styled 컴포넌트 사용
https://www.npmjs.com/package/styled-components
벡틱 따옴표를 사용해서 바로 css를 사용함
App.jsx
style의 자동완성이 되지않아서 확장 프로그램 찾아봄
import reset from "styled-reset";
const GlobalStyle = createGlobalStyle`
${reset}
* {
box-sizing: border-box;
}
body {
background-color: black;
color:white;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
`;
배경색 설정과 폰트 , 폰트색상 설정했다.
function App() {
return (
<>
<GlobalStyle />
<RouterProvider router={router} />
</>
);
}
테스트하기
파이어 베이스를 사용 시 인증 등을 실행할 때 살짝의 로딩이 걸린다.
그래서 로딩을 띄워주는 컴포넌트를 생성할거임
import styled from "styled-components";
const Wrapper = styled.div`
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
`;
const Text = styled.span`
font-size: 24px;
`;
const LoadingScreen = () => {
return (
<Wrapper>
<Text>로딩중...</Text>
</Wrapper>
);
};
export default LoadingScreen;
App.jsx에서 파이어 베이스 테스트를 한다.(로딩테스트)
function App() {
const [isLoading, setIsLoading] = useState(true);
const init = async () => {
//파이어베이스 체크
setTimeout(() => setIsLoading(false), 2000);
};
useEffect(() => {
init();
}, []);
return (
<>
<GlobalStyle />
{isLoading ? <LoadingScreen /> : <RouterProvider router={router} />}
</>
);
}
firebase 새 프로젝트 생성하기
구성 요소 복사해서 사용할거임
firebase설치
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: import.meta.env.VITE_API_KEY,
authDomain: import.meta.env.VITE_AUTH_DOMAIN,
projectId: import.meta.env.VITE_PROJECTID,
storageBucket: import.meta.env.VITE_STORAGE_BUCKET,
messagingSenderId: import.meta.env.VITE_MESSAGEING_SENDERID,
appId: import.meta.env.VITE_APPID,
};
const app = initializeApp(firebaseConfig);
인증 사용하기
파이어베이스 사용 시
이러한 오류가 뜨면 확장 프로그램에 코스를 중지시키면 된다.
firebase.js
인증 기능을 추가한다.
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: import.meta.env.VITE_API_KEY,
authDomain: import.meta.env.VITE_AUTH_DOMAIN,
projectId: import.meta.env.VITE_PROJECTID,
storageBucket: import.meta.env.VITE_STORAGE_BUCKET,
messagingSenderId: import.meta.env.VITE_MESSAGEING_SENDERID,
appId: import.meta.env.VITE_APPID,
};
const app = initializeApp(firebaseConfig);
//파이어베이스 인증
const auth = getAuth();
export { auth };
App.jsx에서 테스트는 주석처리하고
파이어베이스 인증을 준비하는 코드로 대체한다.
CreateUser .jsx
import { useState } from "react";
import styled from "styled-components";
const Wrapper = styled.div`
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 420px;
padding: 50px 0px;
`;
const Title = styled.h1`
font-size: 42px;
`;
const Form = styled.form`
margin-top: 50px;
display: flex;
flex-direction: column;
gap: 10px;
width: 100%;
`;
const Input = styled.input`
padding: 10px 20px;
border-radius: 50px;
border: none;
width: 100%;
font-size: 16px;
&[type="submit"] {
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
`;
const Error = styled.span`
font-weight: 600;
color: tomato;
`;
const CreateUser = () => {
const [isLoading, setLoading] = useState(false);
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const onChange = (e) => {
//이벤트 객체를 분리함 ( target -> name/value )
//console.log(e);
const { name, value } = e.target;
if (name === "name") {
setName(value);
} else if (name === "email") {
setEmail(value);
} else if (name === "password") {
setPassword(value);
}
};
const onSubmit = (e) => {
e.preventDefault();
try {
// create an account
// set the name of the user.
// redirect to the home page
} catch (e) {
// setError
} finally {
setLoading(false);
}
};
return (
<Wrapper>
<Title>Log into 𝕏</Title>
<Form onSubmit={onSubmit}>
<Input
onChange={onChange}
name="name"
value={name}
placeholder="Name"
type="text"
required
/>
<Input
onChange={onChange}
name="email"
value={email}
placeholder="Email"
type="email"
required
/>
<Input
onChange={onChange}
value={password}
name="password"
placeholder="Password"
type="password"
required
/>
<Input
type="submit"
value={isLoading ? "Loading..." : "Create Account"}
/>
</Form>
{error !== "" ? <Error>{error}</Error> : null}
</Wrapper>
);
};
export default CreateUser;
App.jsx에서 wrapper로 감싸서 컨텐츠들이 가운데로 오게 위치한다.
const Wrapper = styled.div`
height: 100vh;
display: flex;
justify-content: center;
`;
return (
<>
<Wrapper>
<GlobalStyle />
{/* 로딩이면 로딩스크린을 보여주고 아니면 router를 보여준다 */}
{isLoading ? <LoadingScreen /> : <RouterProvider router={router} />}
</Wrapper>
</>
);
회원가입
CreateUser.jsx의 submit 시 실제 회원가입을 하도록 코드를 추가한다.
const onSubmit = async (e) => {
e.preventDefault();
if (isLoading || name === "" || email === "" || password === "") return; //만약 이름,이메일,패스워드가 공백이면 리턴함
//회원가입 실행
try {
setLoading(true); //로딩 시작
//유저정보
const credentials = await createUserWithEmailAndPassword(
auth,
email,
password
);
console.log(credentials.user); // 유저 정보 출력
await updateProfile(credentials.user, {
displayName: name, // 이름 저장
});
navigate("/"); //회원가입 완료 후 기본 페이지로
} catch (e) {
// setError
} finally {
setLoading(false);
}
};