inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)

유저 정보 Context에 담아주기(3)

context-api쪽 auth.tsx를 제 나름대로 리팩토리 해보았습니다.

406

rhkdtjd_12
1

[auth.tsx]

import { User } from '@/shared/interfaces/user.interface';
import {
	createContext,
	FC,
	PropsWithChildren,
	useContext,
	useReducer,
	Dispatch,
	ReactNode,
} from 'react';

interface AuthState {
	authenticated: boolean;
	user: User | undefined;
	loading: boolean;
}

export type AuthAction =
	| { type: 'LOGIN'; payload: User }
	| { type: 'LOGOUT' }
	| { type: 'STOP_LOADING' }
	| { type: undefined };

const initialState: AuthState = {
	authenticated: false,
	user: undefined,
	loading: true,
};

const AuthContext = createContext<{
	state: AuthState;
	dispatch: Dispatch<AuthAction>;
}>({
	state: initialState,
	dispatch: () => null,
});

const authReducer = (state: AuthState, action: AuthAction): AuthState => {
	switch (action.type) {
		case 'LOGIN':
			return {
				...state,
				authenticated: true,
				user: action.payload,
			};
		case 'LOGOUT':
			return {
				...state,
				authenticated: false,
				user: undefined,
			};
		case 'STOP_LOADING':
			return {
				...state,
				loading: false,
			};
		default:
			throw new Error(`Unknown action type: ${action.type}`);
	}
};

const AuthProvider: FC<PropsWithChildren<{ children?: ReactNode }>> = ({
	children,
}) => {
	const [state, dispatch] = useReducer(authReducer, initialState);

	return (
		<AuthContext.Provider value={{ state, dispatch }}>
			{children}
		</AuthContext.Provider>
	);
};
const useAuthStateDispatch = () => useContext(AuthContext);

export { AuthProvider, useAuthStateDispatch };

[login.tsx]

import InputGroup from '@/components/ui/field/InputGroup';
import axios from 'axios';
import { AuthAction, useAuthStateDispatch } from 'context/auth';
import { NextPage } from 'next';
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { FormEvent, useState } from 'react';

const LoginPage: NextPage = () => {
	const [username, setUsername] = useState('');
	const [password, setPassword] = useState('');
	const [errors, setErros] = useState<any>({});

	const router = useRouter();
	
	const { dispatch } = useAuthStateDispatch();

	const handleSubmit = async (e: FormEvent) => {
		e.preventDefault();
		try {
			const res = await axios.post(
				'/auth/login',
				{ password, username },
				{ withCredentials: true },
			);

			dispatch({ type: 'LOGIN', payload: res.data?.user });
			router.push('/');
		} catch (error: any) {
			console.log(error);
			setErros(error.response.data || {});
		}
	};

	return (
		<div className="bg-white">
			<div className="flex flex-col items-center justify-center h-screen p-6">
				<div className="w-10/12 mx-auto md:w-96">
					<h1 className="mb-2 text-lg font-medium">로그인</h1>
					<form onSubmit={handleSubmit}>
						<InputGroup
							placeholder="Username"
							value={username}
							setValue={setUsername}
							error={errors.username}
						/>
						<InputGroup
							placeholder="Password"
							value={password}
							setValue={setPassword}
							error={errors.password}
						/>
						<button className="w-full py-2 mb-1 text-xs font-bold text-white uppercase bg-gray-400 border border-gray-400 rounded">
							로그인
						</button>
					</form>
					<small>
						아직 아이디가 없나요?
						<Link href="/register" className="ml-1 text-blue-500 uppercase">
							회원가입
						</Link>
					</small>
				</div>
			</div>
		</div>
	);
};

export default LoginPage;

 

누군가에겐 도움이 되지 않을까해서 남겨 보아요!

답변 0