인프런 커뮤니티 질문&답변

rlawnsgml1997님의 프로필 이미지
rlawnsgml1997

작성한 질문수

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

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

dispatch에서 const dispatch = useContext(DispatchContext); 가 console.log(dispatch)를 하면 null로 출력이 나옵니다.

작성

·

294

0

안녕하세요 강사님,

수업대로 코드를 작성해도 제목과 같이 원하지 않던 오류가 생겨 질문을 드립니다.

아래와 같이 작성했을때, dispatch함수가 function이 아니라는 오류를 내뱉어, 원인을 찾았더니,

useContext(DispatchContext)가 null인 원인이었습니다. 이를 어떻게 고쳐야 정상적으로 작동을 할지 잘 모르겠습니다.

코드는 다음과 같습니다.

 

import axios from "axios";
import { createContext, useContext, useEffect, useReducer } from "react";
import { User } from "../types";

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

export const StateContext = createContext<State>({
    authenticated: false,
    user: undefined,
    loading: true
});

export const DispatchContext = createContext<any>(null);

interface Action {
    type: string;
    payload: any;
}


const reducer = (state: State, { type, payload }: Action) => {
    switch (type) {
        case "LOGIN":
            return {
                ...state,
                authenticated: true,
                user: payload
            }
        case "LOGOUT":
            return {
                ...state,
                authenticated: false,
                user: null
            }
        case "STOP_LOADING":
            return {
                ...state,
                loading: false
            }
        default:
            throw new Error(`Unknown action type: ${type}`)
    }
}



export const AuthProvider = ({ children }: { children: React.ReactNode }) => {

    const [state, defaultDispatch] = useReducer(reducer, {
        user: null,
        authenticated: false,
        loading: true
    })

    console.log("state", state);

    const dispatch = (type: string, payload?: any) => {
        defaultDispatch({ type, payload });
    }

    return (
        <DispatchContext.Provider value={dispatch}>
            <StateContext.Provider value={state}>{children}</StateContext.Provider>
        </DispatchContext.Provider>
    )
}

export function useAuthState() {
    const state = useContext(StateContext);
    //if(!state) throw new Error("Provider is not found");
    return state;
}
export function useAuthDispatch(){
    const dispatch = useContext(DispatchContext);
    //if(!dispatch) throw new Error("Provider is not found");
    return dispatch;
}




/**
 *  
 * <AuthProvider>
 *  <Component {...} />    => Component가 위의 children에 들어감
 * </AuthProvider>
 * 
 * 
 */

위는 context/auth 코드이고, 아래는 pages/api/login 코드입니다.

import React, { useState, useContext, FormEvent} from 'react' import Link from "next/link" import axios from "axios" import InputGroup from "../components/InputGroup" import { useRouter } from 'next/router' import { useAuthDispatch, useAuthState, AuthProvider, StateContext, DispatchContext } from "../context/auth"; const Login = () => { let router = useRouter(); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [errors, setErrors] = useState<any>({}); const dispatch = useAuthDispatch(); //const dispatch = useContext(DispatchContext); const handleSubmit = async (event: FormEvent) =>{ event.preventDefault(); try{ const res = await axios.post("/auth/login",{password, username}, {withCredentials: true}); console.log("res: ",res); dispatch("LOGIN", res.data?.user) router.push('/'); }catch(error: any){ console.log(error || {}); //setErrors(error.response.data || {}); } } return ( <div className="bg-white"> <div className="flex items-center justify-content h-screen p-6"> <div className="w-10/12 h-2/4 mx-auto md:w-96"> <h1 className="mb-2 text-lg text-yellow-500 font-medium">로그인</h1> <AuthProvider> <form onSubmit={handleSubmit} className="h-1/2"> <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 text-xs font-bold text-white uppercase bg-gray-400 border border-gray-400 rounded"> 로그인 </button> </form> </AuthProvider> <small className="text-black"> 아직 아이디가 없나요? <Link href="/login"> <a className="ml-1 text-blue-500 uppercase">회원가입</a> </Link> </small> </div> </div> </div> ) } export default Login

답변

답변을 기다리고 있는 질문이에요
첫번째 답변을 남겨보세요!
rlawnsgml1997님의 프로필 이미지
rlawnsgml1997

작성한 질문수

질문하기