Redux Toolkit
2025. 4. 1. 00:41ㆍFrameworks/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 |