프로젝트 8일차

정지우·2021년 11월 29일
1

Project.zip

목록 보기
4/17
post-thumbnail

파이널 프로젝트 8일차(21-11-29)

user 리덕스 툴킷 로직 구축

📖 회원가입


글로벌 axios 기본 설정

:모든 요청에 적용될 구성 기본(Config Defaults) 값을 지정할 수 있습니다.

axios.defaults.baseURL = 'http://localhost:4000';

e.preventDefault();

: 이벤트를 취소할 수 있는 경우, 이벤트의 전파를 막지않고 그 이벤트를 취소합니다 (mdn)

createAsyncThunk

: 입력 받은 회원가입 정보를 요청 바디에 담아 전송하기 위해 fetchSignUp이라는 thunk를 만듭니다.

  • 리덕스-툴킷에는 thunk 기능이 내장되어있습니다.
  • createAsyncThunk를 사용하여, thunk를 만들 수 있습니다.
export const fetchSignUp = createAsyncThunk(
  'signUp/fetchSignUp',
  async (form) => {
    const { nickname, email, password } = form;
    const response = await axios.post('http://localhost:4000/auth/sign-up', { nickname, email, password });
    return response.data;
  }
)

dispatch(fetchSignUp)

: 유효성 검사가 모두 통과된 경우, submit 버튼을 누르면, dispatch 메소드를 사용하여 thunk를 실행한다.

  const handleSubmit = (e) => {
    e.preventDefault();
    if(nicknameMessage === "" 
       && emailMessage === "" 
       && passwordMessage === "" 
       && confirmPasswordMessage === "") {
      dispatch(fetchSignUp(joinInfo));
    }
    setJoinInfo({
      nickname: '',
      email: '',
      password: '',
      confirmPassword: ''
    })
  • fetchSignUp thunk의 매개변수인 form 자리에 입력 받은 joinInfo 값이 들어옵니다.
  • axios.post() 메소드를 이용해 api 문서에 적시한 해당 엔드포인트에 joinInfo의 데이터 중 { nickname, email, password }를 보내줍니다.
    • confirmPassword 값의 유효성 검사는 프론트에서 처리를 해주었기 때문에 따로 보내주지 않습니다.
  • 요청이 완료되면, 성공 · 실패 여부와 상관 없이 input창의 joinInfo 값들을 초기화합니다.

initialState

const initialState = {
  user: null,
  userError: null,
  isSignUp: false,
  isLogin: false,
  loading: false,
}

createSlice()

: 객체에 reducer함수들을 제공할 수 있고 이를 기반으로 액션 타입문자열과 액션 생성자 함수를 자동으로 생성합니다.

[출처] soyoung210.github.io - Introducing: createSlice

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {},
  extraReducers: {
	// 회원가입
    [fetchSignUp.pending]: (state) => {
      state.loading = true;
    },
    [fetchSignUp.fulfilled]: (state) => {
      state.loading = false;
      state.isSignUp = true;
    },
    [fetchSignUp.rejected]: (state, { payload }) => {
      state.loading = false;
      state.userError = payload;
    },
    // 로그인
    [fetchLogin.pending]: (state) => {
      state.loading = true;
    },
    [fetchLogin.fulfilled]: (state, { payload }) => {
      state.loading = false;
      state.user = payload;
      state.isLogin = true;
    },
    [fetchLogin.rejected]: (state, { payload }) => {
      state.loading = false;
      state.userError = payload;
    },
  }
})
  • 리덕스 툴킷은 액션에 대해 상태를 pending(loading), fulfilled(success), rejected(failure)로 나눕니다.
  • 로딩 이후, 회원가입이 정상적으로 처리되었다면 초기 상태값이 다음과 같이 변경됩니다.
  • [signUp/fetchSignUp/pending] 상태 변화: 로딩중
  • [signUp/fetchSignUp/fulfilled] 상태 변화: 회원 가입 성공

useEffect(() => {}, [(...)])

  • 회원가입 요청에 대한 응답이 에러 메시지가 발생하지 않고, 성공적으로 들어올 경우, 상태값 isSignUp이 true로 바뀌는 것을 확인할 수 있었습니다.
  • Join 페이지에서는 useEffect를 사용하여 isSignUp이 true일 경우 /login 페이지로 전환되도록 설정해줍니다.
  • 에러메시지가 발생할 경우, 화면이 전환되지 않고 에러메시지가 나오도록 해줍니다.
  useEffect(() => {
    if(isSignUp){
      history.push('/login');
    } else {
      setServerErrorMessage(userError);
    }
  },[history, isSignUp, userError])
  • [ history, isSignUp, userError ]
    • eslint가 배열안에 필요한 값들을 자동으로 입력해줍니다.

언제 useEffect가 실행될까요?

  • 컴포넌트 생성 후 처음 화면에 렌더링(표시)
  • 컴포넌트에 새로운 props가 전달되며 렌더링
  • 컴포넌트에 상태(state)가 바뀌며 렌더링

이처럼 매 번 새롭게 컴포넌트가 렌더링될 때 Effect Hook이 실행됩니다.


📖 로그인

handleSubmit

  const handleSubmit = (e) => {
    e.preventDefault();

    if(emailMessage === "" && passwordMessage === "") {
      dispatch(fetchLogin(loginInfo));
    }
    setLoginInfo({
      email: '',
      password: '',
    })
  };

fetchLogin

export const fetchLogin = createAsyncThunk(
  'login/fetchLogin',
  async (form) => {
    const { email, password } = form;
    const response = await axios.post('http://localhost:4000/auth/log-in', { email, password });
    return response.data;
  }
)

initialState

const initialState = {
  user: null,
  userError: null,
  isSignUp: false,
  isLogin: false,
  loading: false,
}

createSlice

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {},
  extraReducers: {
	// 회원가입
    [fetchSignUp.pending]: (state) => {
      state.loading = true;
    },
    [fetchSignUp.fulfilled]: (state) => {
      state.loading = false;
      state.isSignUp = true;
    },
    [fetchSignUp.rejected]: (state, { payload }) => {
      state.loading = false;
      state.userError = payload;
    },
    // 로그인
    [fetchLogin.pending]: (state) => {
      state.loading = true;
    },
    [fetchLogin.fulfilled]: (state, { payload }) => {
      state.loading = false;
      state.user = payload;
      state.isLogin = true;
    },
    [fetchLogin.rejected]: (state, { payload }) => {
      state.loading = false;
      state.userError = payload;
    },
  }
})

useEffect(() => {}. [(...)]

  useEffect(() => {
    if(user){
      history.push('/');
    }
    if(userError){
      setServerErrorMessage(userError);
    }
  }, [history, user, userError])

  • 로그인에 성공하면 쿠키에 jwt 토큰이 들어온 것을 확인할 수 있습니다.
    • 경로: 개발자 도구 > 애플리케이션 > 쿠키

출처

Redux Toolkit 함수 기능 요약

profile
재미를 쫓는 개발자

0개의 댓글