Redux Toolkit

2025. 4. 1. 00:41Frameworks/React

Redux Toolkit

Redux의 복잡성을 줄이기 위해 개발된 Redux 공식 도구로, Redux의 모범 사례를 기본으로 내장하고 있습니다.

npm install @reduxjs/toolkit react-redux

Redux Toolkit 사용 예제:

// features/user/userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

// 비동기 액션 생성
export const loginUser = createAsyncThunk(
  'user/login',
  async (credentials, { rejectWithValue }) => {
    try {
      const response = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(credentials)
      });
      
      if (!response.ok) {
        throw new Error('로그인 실패');
      }
      
      return await response.json();
    } catch (error) {
      return rejectWithValue(error.message);
    }
  }
);

// Slice 생성 (액션 + 리듀서)
const userSlice = createSlice({
  name: 'user',
  initialState: {
    user: null,
    isAuthenticated: false,
    loading: false,
    error: null
  },
  reducers: {
    logout: (state) => {
      state.user = null;
      state.isAuthenticated = false;
    },
    updateProfile: (state, action) => {
      state.user = { ...state.user, ...action.payload };
    }
  },
  extraReducers: (builder) => {
    builder
      .addCase(loginUser.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(loginUser.fulfilled, (state, action) => {
        state.loading = false;
        state.user = action.payload;
        state.isAuthenticated = true;
      })
      .addCase(loginUser.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload;
      });
  }
});

// 액션 생성자 내보내기
export const { logout, updateProfile } = userSlice.actions;

// 리듀서 내보내기
export default userSlice.reducer;
// app/store.js
import { configureStore } from '@reduxjs/toolkit';
import userReducer from '../features/user/userSlice';
import postsReducer from '../features/posts/postsSlice';

export const store = configureStore({
  reducer: {
    user: userReducer,
    posts: postsReducer
  }
});
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);
// components/LoginPage.js
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { loginUser } from '../features/user/userSlice';

function LoginPage() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  
  const { user, isAuthenticated, loading, error } = useSelector(state => state.user);
  const dispatch = useDispatch();

  const handleSubmit = (e) => {
    e.preventDefault();
    dispatch(loginUser({ username, password }));
  };

  if (isAuthenticated) {
    return <p>이미 로그인되었습니다, {user.username}님!</p>;
  }

  return (
    <form onSubmit={handleSubmit}>
      <h2>로그인</h2>
      {error && <p className="error">{error}</p>}
      <input
        type="text"
        placeholder="사용자명"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        disabled={loading}
      />
      <input
        type="password"
        placeholder="비밀번호"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        disabled={loading}
      />
      <button type="submit" disabled={loading}>
        {loading ? '로그인 중...' : '로그인'}
      </button>
    </form>
  );
}

export default LoginPage;

 

'Frameworks > React' 카테고리의 다른 글

React와 API 연동하기  (0) 2025.04.01
Context API vs Redux  (0) 2025.04.01
Redux  (0) 2025.04.01
React 상태 관리  (0) 2025.04.01
복잡한 라우팅 구성 예제  (0) 2025.04.01