React + GraphQL - Typescript 시작하기 - 3

HOONEY·2022년 1월 10일
0

React

목록 보기
3/5
post-thumbnail

Express + GraphQL + MongoDB 시작하기 - 4에서 이어지는 내용

https://velog.io/@mkh1213/Express-GraphQL-MongoDB-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-4
update, delete 화면쪽 코드 작성

  • 쿠키 라이브러리 설치
npm i react-cookie

로그아웃

  • src/index.tsx 수정
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { client } from './apollo/client';
import { ApolloProvider } from '@apollo/react-hooks';
import { CookiesProvider } from 'react-cookie';

ReactDOM.render(
  <ApolloProvider client={client}>
    <React.StrictMode>
        <CookiesProvider>
          <App />
        </CookiesProvider>
    </React.StrictMode>
  </ApolloProvider>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
  • <App />을 CookiesProvider로 감싸기
  • src/pages/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";
import { useCookies } from "react-cookie";

function Home() {
  const [cookies, setCookies, removeCookie] = useCookies(['test']);
  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}) => {
      if (getUser) {
        const expireDate = new Date();
        expireDate.setMonth(expireDate.getMonth() + 1);
        alert("로그인 성공!");
        setCookies('test', getUser.email, {path:'/', expires : expireDate});
      } else {
        alert("로그인 실패!")
      }
    }
  });
  const onSignOut = () => {
    console.log('signout');
    removeCookie('test');
    alert("로그아웃 성공!");
  }
  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" style={cookies.test !== undefined ? {display: "none"} : {display: ""}}  onClick={() => onSignIn({variables: {email, password}})}>Sign In</Button>
        <Button variant="text" style={cookies.test !== undefined ? {display: ""} : {display: "none"}}  onClick={() => onSignOut()}>Sign Out</Button>
        <Button variant="text">
          <Link to="/signup" style={{ textDecoration: 'none', color: '#1976d2' }}>Sign Up</Link>
        </Button>
        
      </Box>
    </div>
  );
}

export default Home;
  • 로그인, 로그아웃 버튼만들어서 cookie가 있을 경우 로그아웃버튼, 없을 경우 로그인 버튼이 나타나도록 수정
  • 쿠키의 유효기간은 1달
  • 로그아웃 시 쿠키 제거

회원정보 수정 페이지

  • src/components/Navigation.tsx 수정
import React from "react";
import { Link } from "react-router-dom";
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { useCookies } from "react-cookie";

function Navigation() {
  const [cookies, setCookies, removeCookie] = useCookies(['test']);

  return (
    <div className="nav">
      <Box sx={{ display: 'flex', alignItems: 'center', textAlign: 'center' }}>
        <Button>
          <Link to="/" style={{ textDecoration: 'none', color: '#1976d2' }}>Home</Link>
        </Button>
        <Button>
          <Link to="/modify" style={{ textDecoration: 'none', color: '#1976d2' }}>Modify</Link>
        </Button>
      </Box>
    </div>
  );
}

export default Navigation;
  • Modify 추가, Cookie 사용
  • src/Router.tsx 수정
import React from "react";
import { BrowserRouter , Route, Routes } from "react-router-dom";
import Navigation from "./components/Navigation";
import Home from "./pages/Home";
import Modify from "./pages/Modify";
import SignUp from "./pages/SignUp";

function Router() {
  return (
    <BrowserRouter >
      <Navigation />
      <br />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/signup" element={<SignUp />} />
        <Route path="/modify" element={<Modify />} />
      </Routes>
    </BrowserRouter >
  );
}

export default Router;
  • Modify 추가
  • src/gql/modify.gql.ts 생성
import gql from 'graphql-tag';

export const GET_USER_BY_EMAIL = gql`
    query getUserByEmail(
        $email: String!
    ) {
        getUserByEmail(
            email: $email
        ) {
            email
            password
            name
        }
    }
`
  • 이메일을 통해 회원정보를 가져올 수 있도록 쿼리를 작성
  • src/pages/Modify.tsx 생성
import React, { useState, useEffect } from "react";
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
import { useMutation, useQuery } from '@apollo/react-hooks';
import { useCookies } from "react-cookie";
import { GET_USER_BY_EMAIL } from "../gql/modify.gql";

function Modify() {
    const [cookies, setCookies, removeCookie] = useCookies(['test']);
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [name, setName] = useState('');
    const {loading, error, data, refetch} = useQuery(GET_USER_BY_EMAIL, {
        fetchPolicy: 'cache-and-network',
        variables: { email: cookies.test },
    });
      
    useEffect(() => {
        if (data?.getUserByEmail) {
            setEmail(data.getUserByEmail.email);
            setPassword(data.getUserByEmail.password);
            setName(data.getUserByEmail.name);
        }
    }, [data]);

    const onModify = async (e: any) => {
        console.log("modify!");
    }

    return (
    <div>
        <Box
	        onSubmit={onModify}
            component="form"
            sx={{
                '& > :not(style)': { m: 1, width: '25ch' },
            }}
            noValidate
            autoComplete="off"
        >
        <TextField id="standard-email-input" label="Email" variant="standard"  value={email} />
        <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">Modify</Button>
        </Box>
    </div>
    );
}

export default Modify;

다음 포스팅에서 이어서...

profile
기록하는 블로그

0개의 댓글