하이어+플러스! 직원을 위해 제가 구축한 방법은 다음과 같습니다(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;

RootState 및 AppDispatch는 useSelector 및 useDispatch를 사용하는 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 , signUpUserEmailAndPassword 및 signoutUser 함수를 사용하여 auth reducer의 초기 상태를 설정합니다.
signInWithEmailAndPassword 및 signUpUserEmailAndPassword 모두 인증 사용자의 문자열화된 버전을 반환합니다.

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에서 이러한 함수를 호출할 것입니다.
createAsyncThunk 및 docs에서 작동하는 방식에 대해 자세히 살펴보십시오.


감속기



응답 상태를 처리하고 그에 따라 상태를 설정했습니다..fulfilled 및 signInWithEmailAndPassword에 대한 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;



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

좋은 웹페이지 즐겨찾기