• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    미해결

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

22.11.07 01:19 작성 조회수 217

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

답변 0

답변을 작성해보세요.

답변을 기다리고 있는 질문이에요.
첫번째 답변을 남겨보세요!