React + GraphQL - Typescript 시작하기 - 4

HOONEY·2022년 1월 12일
0

React

목록 보기
4/5
post-thumbnail

회원정보수정

  • src/pagaes/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, PATCH_USER } from "../gql/modify.gql";

function Modify() {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [name, setName] = useState('');
    
    const [cookies, setCookies, removeCookie] = useCookies(['test']);
    
    const [patchUserMutation] = useMutation(PATCH_USER);

    const {loading, error, data, refetch} = useQuery(GET_USER_BY_EMAIL, {
        fetchPolicy: 'cache-and-network',
        variables: { email: cookies.test },
    });
    useEffect(() => {
        if (!cookies.test) {
            navigate("/");
        }
    }, [])  
    useEffect(() => {
        if (data?.getUserByEmail) {
            setEmail(data.getUserByEmail.email);
            setPassword(data.getUserByEmail.password);
            setName(data.getUserByEmail.name);
        }
    }, [data]);

    const onModify = async (e: any) => {
        e.preventDefault();
        try {
            const {
                data: { patchUser },
            } = await patchUserMutation({
                variables: {
                    email,
                    password,
                    name
                },
            });
            if (patchUser) {
                alert("회원정보 수정 성공!");
            }
        } catch (error: any) {
            console.error(`onModify Error = ${error}`);
        }
    }

    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;
  • useEffect를 통해 페이지가 useQuery의 결과에 따라 email, password, name의 상태를 변경해줌.
  • useEffect의
    useEffect(() => {
        if (data?.getUserByEmail) {
            setEmail(data.getUserByEmail.email);
            setPassword(data.getUserByEmail.password);
            setName(data.getUserByEmail.name);
        }
    }, [data]);

마지막 대괄호 안에 변수를 넣어주면 그 변수의 상태가 변할 때 마다 useEffect가 실행된다. 비워둘 경우 처음 렌더링 될 때만 실행된다.

  • Cookie가 없을 경우 강제로 HOME으로 이동시킨다.
  • 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
        }
    }
`
export const PATCH_USER = gql`
    mutation patchUser(
        $email: String!
        $password: String!
        $name: String!
    ) {
        patchUser(
            email: $email
            password: $password
            name: $name
        ) {
            email
        }
    }
`;
  • 회원정보 수정을 위한 쿼리 작성

회원정보수정 테스트해보기

  • npm run start로 서버와 화면을 실행
  • 기존

  • 회원정보 수정 (비밀번호와 이름을 test2로 변경, email은 수정 불가)
  • 결과

  • 새로고침을 해도 test2인 상태

회원탈퇴

  • 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, PATCH_USER, DELETE_USER } from "../gql/modify.gql";

function Modify() {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [name, setName] = useState('');
    
    const [cookies, setCookies, removeCookie] = useCookies(['test']);
    
    const [patchUserMutation] = useMutation(PATCH_USER);
    const [deleteUserMutation] = useMutation(DELETE_USER);

    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) => {
        e.preventDefault();
        try {
            const {
                data: { patchUser },
            } = await patchUserMutation({
                variables: {
                    email,
                    password,
                    name
                },
            });
            if (patchUser) {
                alert("회원정보 수정 성공!");
            }
        } catch (error: any) {
            console.error(`onModify Error = ${error}`);
        }
    }

    const onDrop = async () => {
        const confirmText = "탈퇴하시겠습니까?";
        if (window.confirm(confirmText)) {
            try {
                const {
                    data: { deleteUser },
                } = await deleteUserMutation({
                    variables: {
                        email,
                        password,
                    },
                });
                if (deleteUser) {
                    alert("회원탈퇴 성공!");
                }
            } catch (error: any) {
                console.error(`onDrop Error = ${error}`);
            }
        }
    }

    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>
            <Button variant="text" onClick={onDrop}>Drop</Button>
            </Box>
        </div>
    );
}

export default Modify;
  • MODIFY 버튼 옆 DROP버튼을 만들어 클릭할 때 useMutation이 실행되도록 했다.
  • 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
        }
    }
`
export const PATCH_USER = gql`
    mutation patchUser(
        $email: String!
        $password: String!
        $name: String!
    ) {
        patchUser(
            email: $email
            password: $password
            name: $name
        ) {
            email
        }
    }
`;

export const DELETE_USER = gql`
    mutation deleteUser(
        $email: String!
        $password: String!
    ) {
        deleteUser(
            email: $email
            password: $password
        ) {
            email
        }
    }
    `;
  • deleteUser를 추가했다.

회원탈퇴 테스트 해보기

  • npm run start로 서버와 화면을 실행
  • test@test.com / test로 로그인한 상태에서 MODIFY화면에서 DROP버튼 클릭
  • 탈퇴 성공
  • 탈퇴 후 로그인 시도 시 로그인이 되질 않는다.

회원탈퇴 후 처리

  • 회원탈퇴 후 강제로 HOME으로 화면이동
    상단에 import
import { useNavigate } from "react-router-dom";
....
....
if (deleteUser) {
	alert("회원탈퇴 성공!");
	navigate("/");
}
  • 쿠키 삭제
    src/pages/Modify.tsx 수정
if (deleteUser) {
	alert("회원탈퇴 성공!");
	removeCookie('test');
    navigate("/");
}
  • MODIFY접근 제한 또는 버튼 숨김처리
    src/components/Navigation.tsx 수정
<Button style={cookies.test === undefined ? {display: 'none'} : {display: ''}}>
	<Link to="/modify" style={{ textDecoration: 'none', color: '#1976d2' }}>Modify</Link>
</Button>

결론

  • Express + Graphql + MongoDB + React-typescript를 통해 간단한 CRUD를 만들어보았다.
  • Graphql에 대한 자세한 공부가 필요하다고 느꼈다.(RestAPI와 차이점, 장단점)
  • Typescript에 대한 공부가 필요하다고 느꼈다.
profile
기록하는 블로그

0개의 댓글

관련 채용 정보