하이어+플러스! 직원을 위해 제가 구축한 방법은 다음과 같습니다(Redux - Auth).

목적: 응시자는 로그인, 구글 로그인, 회원가입, 로그아웃을 할 수 있습니다.

Redux를 상태 관리, 특히 Redux 툴킷으로 사용하고 있습니다. 이전보다 훨씬 간단하게 redux로 작업할 수 있도록 해주는 패키지입니다. Redux Toolkit here 에 대한 자세한 내용을 읽을 수 있습니다.

npm을 사용하여 프로젝트에 추가했습니다.npm install @reduxjs/toolkit @react-redux
문서(위 링크)의 지침에 따라 설정했습니다.

모든 redux 코드가 저장될 app 폴더를 생성하여 리듀서를 프로젝트와 관련된 기능(인증, 프로필, 작업 회사)으로 분리했습니다.

Redux 툴킷 구성



store.ts - redux 및 내 감속기 구성

import { configureStore } from '@reduxjs/toolkit';
import authReducer from './features/auth/authSlice';
import profileReducer from './features/profile/profileSlice';
import jobReducer from './features/job/jobSlice';
import companyReducer from './features/company/companySlice';

export const store = configureStore({
  reducer: {
     auth: authReducer,
     profile: profileReducer,
     job: jobReducer,
     company: companyReducer,
  },
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;

// Inferred type: {users: UsersState}
export type AppDispatch = typeof store.dispatch;

RootStateAppDispatchuseSelectoruseDispatch를 사용하는 Redux 툴킷의 버전입니다.

hooks.ts - redux 툴킷의 유형이 지정된 버전의 상태 및 작업 후크를 내보냅니다.

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;


index.tsx - 스토어 공급자를 전체 앱에 전달

import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import 'tw-elements';
import './index.css';
import App from './App';
import { store } from './app/store';
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root')!);
root.render(
 <BrowserRouter>
   <Provider store={store}>
     <App />
   </Provider>
 </BrowserRouter>
);



유형, 작업 및 리듀서: 인증 상태



유형



인사이드app > features > auth > authTypes.ts내 로그인 정보 및 가입 정보에 대한 데이터 유형입니다.

export type LoginFields = {
 email: string;
 password: string;
};
export type SignUpFields = {
 displayName: string;
 email: string;
 password: string;
};



행위



인사이드app > features > auth > authSlice.tsDB의 signInWithGoogle , signInWithEmailAndPassword , signUpUserEmailAndPasswordsignoutUser 함수를 사용하여 auth reducer의 초기 상태를 설정합니다.
signInWithEmailAndPasswordsignUpUserEmailAndPassword 모두 인증 사용자의 문자열화된 버전을 반환합니다.

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

import {
 signInWithGooglePopup,
 signInEmailAndPassword,
 signUpEmailAndPassword,
 logoutUser,
} from '../../../utils/firebase/firebase.utils';
import { SignUpFields, LoginFields } from './authTypes';

interface authState {
 isSignedIn: boolean;
 currentUser: { uid: string; displayName: string };
 isLoading: boolean;
 signUpError: string;
 signInError: string;
 successMessage: string;
}
const initialState: authState = {
 isSignedIn: false,
 currentUser: { uid: '', displayName: '' },
 isLoading: false,
 signUpError: '',
 signInError: '',
 successMessage: '',
};

// ------- AUTH ACTIONS --------------------------------
export const signInWithGoogle = createAsyncThunk(
    'user/signInWithGoogle',
    async () => {
        await signInWithGooglePopup();
    }
);
export const signInWithEmailAndPassword = createAsyncThunk(
    'user/signInEmailAndPassword',
    async (formFields: LoginFields) => {
        const { user } = await signInEmailAndPassword(
            formFields.email,
            formFields.password
        );
        return JSON.stringify(user);
    }
);
export const signUpUserEmailAndPassword = createAsyncThunk(
    'user/signUpUserEmailAndPassword',
    async (formFields: SignUpFields) => {
        const user = await signUpEmailAndPassword(formFields);
        return JSON.stringify(user);
    }
);
export const signoutUser = createAsyncThunk('user/signoutUser', async () => {
    return await logoutUser();
});


signInWithGoogle() - Google func로 로그인 호출
signInWithEmailAndPassword() - 프런트엔드에서 args를 가져오고 데이터를 먼저 직렬화해야 하므로 반환하기 전에 사용자 데이터를 문자열화합니다.
signUpUserEmailAndPassword() - 프런트엔드에서 args를 가져오고 도우미 기능을 전달합니다. 다시 돌아오는 사용자를 문자열화합니다.
signoutUser() - 로그아웃 도우미 기능을 호출합니다.

UI에서 이러한 함수를 호출할 것입니다.
createAsyncThunkdocs에서 작동하는 방식에 대해 자세히 살펴보십시오.


감속기



응답 상태를 처리하고 그에 따라 상태를 설정했습니다..fulfilledsignInWithEmailAndPassword에 대한 signUpUserEmailAndPassword 응답 상태에서 데이터를 다시 가져와 구문 분석하고 상태로 설정합니다.

const authSlice = createSlice({
    name: 'auth',
    initialState,
    reducers: {

        setSignedIn(state, action) {
            state.isSignedIn = action.payload.signedIn;
            state.currentUser = action.payload.currentUser;
        },
        setSignupError(state, action) {
            state.signUpError = action.payload;
        },
        resetError(state) {
            state.signInError = '';
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(signInWithGoogle.rejected, (_, action) => {
                console.log('something went wrong with google sign-in', action.error);
            })
            // ---------------------------------------- SIGN IN ACTIONS ---------------------------------
            .addCase(signInWithEmailAndPassword.pending, (state) => {
                state.isLoading = true;
            })
            .addCase(signInWithEmailAndPassword.fulfilled, (state, action) => {
                const { uid, displayName } = JSON.parse(action.payload);
                state.isLoading = false;
                state.currentUser = { uid, displayName };
            })
            .addCase(signInWithEmailAndPassword.rejected, (state) => {
                state.isLoading = false;
                state.signInError = 'User does not exist in the database';
            })
            // --------------------------------------- SIGN UP ACTIONS ---------------------------------
            .addCase(signUpUserEmailAndPassword.pending, (state) => {
                state.isLoading = true;
            })
            .addCase(signUpUserEmailAndPassword.fulfilled, (state, action) => {
                const { displayName, uid } = JSON.parse(action.payload);
                state.isLoading = false;
                state.currentUser = { uid, displayName };
            })
            .addCase(signUpUserEmailAndPassword.rejected, (state, { error }) => {
                state.isLoading = false;
                state.signUpError = error.code;
            })
            // --------------------------------------- SIGN OUT ACTIONS ---------------------------------
            .addCase(signoutUser.fulfilled, (state) => {
                state.isLoading = false;
                state.isSignedIn = false;
            });
    },
});


export const { resetError, setSignupError, setSignedIn } = authSlice.actions;
export default authSlice.reducer;



프로젝트의 인증/리덕스 부분은 여기까지입니다. 계속 지켜봐 주세요!

좋은 웹페이지 즐겨찾기