Joon's Space
[React] authentication front-end (log-in 페이지 ) (1) 본문
Local State ?
local state 는 local storage ( HTML5에서 브라우저에 추가된 저장소로, 브라우저가 종료되어도 그대로 남아있음. ) 에 state 값을 저장해서 사용 할 수 있는 것.
LogIn & LogOut Authentication
// Apollo.ts
import { ApolloClient, InMemoryCache } from "@apollo/client";
export const client = new ApolloClient({
uri: 'http://localhost:4000/graphql',
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
isLoggedIn: {
read() {
return false;
},
},
},
},
},
}),
});
Apollo.ts 부분에서 cache 에서 다음과 같이 Query 를 작성해주고,
// App.tsx
import React from 'react';
import { LoggedOutRouter } from './routers/logged-out-router';
import { gql, useQuery } from '@apollo/client';
const IS_LOGGED_IN = gql`
query isLoggedIn {
isLoggedIn @client
}
`
function App() {
const { data } = useQuery(IS_LOGGED_IN);
console.log(data);
return <LoggedOutRouter />;
}
export default App;
IS_LOGGED_IN 에서 query를 client cache에 요청하여 (요청할 field 뒤에 @client를 붙인다.), useQuery를 이용하여 값을 { data } 에 저장하여 콘솔에 출력한다.
이제 isLoggedIn 필드 값이 true, false 인지에 따라 LoggedOutRouter, LoggedInRouter를 조건에 맞게 리턴해줄 수 있게 해준다.
function App() {
const {
data: { isLoggedIn }
} = useQuery(IS_LOGGED_IN);
return isLoggedIn? <LoggedInRouter /> : <LoggedOutRouter />;
}
log-out-router.tsx 수정 (local state를 apollo client 로 변경)
query에서 항상 isLoggedIn은 false 이기 때문에, react variables 이라는 것을 사용한다. (Apollo Client 의 새 기능)
React variables 는 application 어디에서나 읽고 수정할 수 있다. GraphQL operation 을 사용할 필요가 없다. 이 variables의 저장은 apollo client에 된다.
Reactive variables의 값이 변경 되면, 그 필드를 갖는 쿼리들은 자동으로 새로고침 된다.
makeVar를 이용해서 react variables을 다음과 같이 생성한다.
export const isLoggedInVar = makeVar(false);
isLoggedInVar 변수를 다른 파일에서도 사용할 것 이기 때문에 export 해준다.
// logged-out-router.tsx
import React from "react";
import { isLoggedInVar } from "../apollo";
export const LoggedOutRouter = () => {
const onClick = () => {
isLoggedInVar(true);
};
return (
<div>
<h1>Logged Out</h1>
<button onClick={onClick}>Click to login</button>
</div>
);
};
다음과 같이 Click to login 버튼을 누르면 isLoggedInVar 의 값이 true로 바뀌고, App.tsx 는 LoggedInRouter를 반환하게 될 것이다.
그리고 query 요청해여 받아서 저장하지 않고, hook을 이용해서 reactive variables 의 값을 받아 사용할 수 있다. (useReactiveVar 함수 사용)
const isLoggedIn = useReactiveVar(isLoggedInVar);
그렇다면 App.tsx 파일 코드는 훨씬 더 간결해 진 것을 볼 수 있다.
// App.tsx
import React from 'react';
import { LoggedOutRouter } from './routers/logged-out-router';
import { gql, useQuery, useReactiveVar } from '@apollo/client';
import { LoggedInRouter } from './routers/logged-in-router';
import { isLoggedInVar } from './apollo';
function App() {
const isLoggedIn = useReactiveVar(isLoggedInVar);
return isLoggedIn? <LoggedInRouter /> : <LoggedOutRouter />;
}
export default App;
logged-in-router.tsx 도 logout 버튼을 만들어 isLoggedInVar 가 다시 false로 바뀌게 해준다.
// logged-in-router.tsx
import React from "react";
import { isLoggedInVar } from "../apollo";
export const LoggedInRouter = () => (
<div>
<h1>Logged In</h1>
<button onClick={() => isLoggedInVar(false)}>Log Out</button>
</div>
);
Form
React Hook Form : 리액트에서 form을 다루는 것을 좀 더 쉽게 도와주는 라이브러리.
React Hook Form 패키지 설치
npm i react-hook-form
useForm 을 이용하여, unchaged, default event등등 잡다한 것들을 피해서 form을 생성할 수 있다.
// logged-out-router.tsx
import React from "react";
import { isLoggedInVar } from "../apollo";
import { useForm } from "react-hook-form";
export const LoggedOutRouter = () => {
const { register, watch } = useForm();
console.log(watch());
return (
<div>
<h1>Logged Out</h1>
<form>
<div>
<input {...register("email")} name="email" type="email" required placeholder= "email" />
</div>
<div>
<input {...register("password")} name="password" type="password" required placeholder="password" />
</div>
<button className="bg-yellow-300 text-white">Submit</button>
</form>
</div>
);
};
input 안에 {...register("")} 만 넣어서 사용 할 수 있다.
register는 input 안 value 값의 validation을 쉽게 할 수 있도록 도와주는데 그 validation 옵션(minLength, maxLength 등등)은 register 괄호 속에 넣어서 사용 할 수 있다.
그리고 useForm 의 watch 함수를 console 창에 출력 해 보면, input 창에 입력 할 때마다 입력한 값이 출력 되는 것을 확인 할 수 있다.
그동안 react에서 form부분에서 구현해야 할 것들이 많았기 때문에 다음과 같이 useForm을 이용하여 코드를 간결하게 표현할 수 있다는 것에 react-hook-form 의 기능에대해 감탄하였다.!!
그 외의 추가 내용은 아래 링크에서 확인
https://react-hook-form.com/api/useform/register/
useForm 에서는 submit을 다루는 handleSubmit함수도 내장되어 있다. 이때, onSubmit 함수를 구현해주어야 한다.
그리고 handleSubmit 안 인자에는 2개의 함수를 넣을 수 있는데, 유효성 검사를 통과했을 때 실행되는 함수(onSubmit), 통과하지 못했을 때 실행되는 함수(onInValid) 를 넣는다.
정규 표현식
register 안에 옵션에 pattern 을 추가 설정해서 정규 표현식을 사용 할 수 도 있다.
{...register("email", {required: true, pattern: /^[A-Za-z0-9._%+-]+@gmail.com$/,})}
다음과 같이 react-hook-form 의 useForm 을 이용하여 validate가 훨씬 더 간결해 진 것을 볼 수 있다.
Router
typescript 를 위한 react-router-dom 패키지 설치 (typescript 에 대한 react-router-dom 에는 type 이 없기 때문에 따로 declare 해주거나, type을 포함한 package를 새로 설치해야함)
npm install @types/react-router-dom
위에서 만든 log out 페이지는 다시 route를 이용해서 작성해주고
src에 pages 폴더를 만들어, login, create-account 페이지 작성을 위한 파일을 각각 생성해준다.
// logged-out-router.tsx
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { Login } from "../pages/login";
import { CreateAccount } from "../pages/create-account";
export const LoggedOutRouter = () => {
return <Router>
<Switch>
<Route path="/create-account">
<CreateAccount />
</Route>
<Route path="/">
<Login />
</Route>
</Switch>
</Router>
};
// login.tsx
import React from "react";
export const Login = () => {
return <span>Login</span>;
};
// create-account.tsx
import React from "react";
export const CreateAccount = () => {
return <span>Create Account</span>;
};
'Web > React' 카테고리의 다른 글
[React] React + Firebase 연동 (setup, login, profile) (1) (0) | 2022.02.16 |
---|---|
[React] authentication front-end (tailwindcss로 페이지 구현) (2) (0) | 2021.08.01 |
[React] authentication front-end (log-in, create account, etc) (0) | 2021.07.28 |
[TailwindCSS, Apollo GraphQL] frontend setup (0) | 2021.07.26 |
[React] React Hooks (useState) 1 (0) | 2021.07.18 |