React + GraphQL - Typescript 시작하기 - 2

HOONEY·2022년 1월 6일
0

React

목록 보기
2/5
post-thumbnail

CSS작업을 피하기 위해 라이브러리 설치

  • Material UI 설치
npm install @mui/material @emotion/react @emotion/styled

회원등록 페이지

  • src/gql/signup.gql.ts 파일 생성
import { gql } from "@apollo/client";

export const POST_USER = gql`
    mutation PostUser(
        $email: String!
        $password: String!
        $name: String!
    ) {
    postUser(
        email: $email
        password: $password
        name: $name
    ) {
        email
    }
  }
`;
import React, { useState } from "react";
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
import { POST_USER } from "../gql/signup.gql";
import { useMutation } from "@apollo/client";
import { useNavigate } from "react-router-dom";

function SignUp() {
  const navigate = useNavigate();
  
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [name, setName] = useState('');
  
  const [postUserMutation] = useMutation(POST_USER);
    
  const onSignUp = async (e: any) => {
    e.preventDefault();
    try {
      const {
        data: { postUser },
      } = await postUserMutation({
        variables: {
          email,
          password,
          name,
        },
      });
      if (postUser) {
        alert("회원가입 성공!");
        navigate("/");
      }
    } catch (error: any) {
      console.error(`onSignUp Error = ${error}`);
    }
  }
  return (
    <div>
      <Box
        onSubmit={onSignUp}
        component="form"
        sx={{
          '& > :not(style)': { m: 1, width: '25ch' },
        }}
        noValidate
        autoComplete="off"
      >
        <TextField id="standard-email-input" label="Email" variant="standard" value={email} onInput={(e:any) => setEmail(e.target.value)} />
        <TextField id="standard-password-input" type="password" label="Password" variant="standard" value={password} onInput={(e:any) => setPassword(e.target.value)}  />
        <TextField id="standard-name-input" label="Name" variant="standard" value={name} onInput={(e:any) => setName(e.target.value)}  />
        <Button variant="text" type="submit">Sign Up</Button>
      </Box>
    </div>
  );
}

export default SignUp;
  • Hook을 사용하기 때문에 email, password, name을 useState로 초기화를 해준다.
  • Box, TextField는 Material UI의 컴포넌트이고 따로 CSS를 안해도 이쁘다.
  • useMutation, useQuery 등은 @apollo/client에서 제공하는 컴포넌트로 grqphql을 hook처럼 사용할 수 있게 도와준다.

로그인 기능

  • Home.tsx 수정
import React, { useState } from "react";
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
import { Link } from "react-router-dom";
import { GET_USER } from "../gql/home.gql";
import { useLazyQuery } from "@apollo/client";

function Home() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [onSignIn, {loading, error}] = useLazyQuery(GET_USER, {
    fetchPolicy: "cache-and-network",
    onError: error => {
      console.error(error);
      alert(error.message);
    },
    onCompleted: ({getUser}) => {
      console.log(getUser);
    }
  });

  return (
    <div>
      <Box
        component="form"
        sx={{
          '& > :not(style)': { m: 1, width: '25ch' },
        }}
        noValidate
        autoComplete="off"
      >
        <TextField id="standard-email-input" label="Email" variant="standard"  value={email} onInput={(e:any) => setEmail(e.target.value)} />
        <TextField id="standard-password-input" type="password" label="Password" variant="standard"  value={password} onInput={(e:any) => setPassword(e.target.value)} />
        <Button variant="text" onClick={() => onSignIn({variables: {email, password}})}>Sign In</Button>
        <Button variant="text">
          <Link to="/signup" style={{ textDecoration: 'none', color: '#1976d2' }}>Sign Up</Link>
        </Button>
        
      </Box>
    </div>
  );
}

export default Home;
  • email과 password를 입력할 수 있는 곳과 버튼을 만들어준다.
  • 로그인은 화면에서 입력받은 파라미터를 서버로 보내주고, 그 값과 서버에서 DB에 저장되어 있는 email과 password를 비교 하여 로그인 처리를 해준다.
  • 새롭게 쓰인 useLazyQuery는 useQuery와 비슷한 역할을 한다.
  • useQuery는 컴포넌트가 마운트되고 렌더링 될 때 자동으로 실행
  • useLazyQuery는 특정 액션을 취했을 때 실행

fetchPolicy 옵션이란?

Apollo client는 서버로부터 데이터를 받아오는데, 이 데이터를 캐시에 담아두었다가 같은 쿼리를 요청하면 캐시에 저장된 것을 다시 사용하거나, 새로 받아올 수 있는데 이를 정할 수 있는 것.
자세한 내용은 하단의 링크 참조
https://www.apollographql.com/docs/react/data/queries/#setting-a-fetch-policy

다음 포스팅부터 CRUD에 필요한 서버쪽 코드 작성

이어서

https://velog.io/@mkh1213/Express-GraphQL-MongoDB-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-4

profile
기록하는 블로그

0개의 댓글