이 글은 velopert님의 벨로퍼트와 함께하는 모던 리액트를 공부하며 쓴 글입니다.
리덕스 모듈이란?
- 액션 타입, 액션 생성함수, 리듀서가 모두 모여있는 자바스크립트 파일을 말한다.
- 이와 같은 항목을 하나의 파일에 몰아서 작성하는 방식을 Ducks 패턴이라고 한다.
프로젝트에 리덕스 적용
- react-redux 라이브러리 설치
$ yarn add react-redux
counter 모듈 만들기
modules/counter.js
/* 액션 타입 만들기 */
// Ducks 패턴을 따를땐 액션의 이름에 접두사를 넣어주세요.
// 이렇게 하면 다른 모듈과 액션 이름이 중복되는 것을 방지 할 수 있습니다.
const SET_DIFF = 'counter/SET_DIFF';
const INCREASE = 'counter/INCREASE';
const DECREASE = 'counter/DECREASE';
/* 액션 생성함수 만들기 */
// 액션 생성함수를 만들고 export 키워드를 사용해서 내보내주세요.
export const setDiff = diff => ({ type: SET_DIFF, diff });
export const increase = () => ({ type: INCREASE });
export const decrease = () => ({ type: DECREASE });
/* 초기 상태 선언 */
const initialState = {
number: 0,
diff: 1
};
/* 리듀서 선언 */
// 리듀서는 export default 로 내보내주세요.
export default function counter(state = initialState, action) {
switch (action.type) {
case SET_DIFF:
return {
...state,
diff: action.diff
};
case INCREASE:
return {
...state,
number: state.number + state.diff
};
case DECREASE:
return {
...state,
number: state.number - state.diff
};
default:
return state;
}
}
todos 모듈 만들기
modules/todos.js
/* 액션 타입 선언 */
const ADD_TODO = 'todos/ADD_TODO';
const TOGGLE_TODO = 'todos/TOGGLE_TODO';
/* 액션 생성함수 선언 */
let nextId = 1; // todo 데이터에서 사용 할 고유 id
export const addTodo = text => ({
type: ADD_TODO,
todo: {
id: nextId++, // 새 항목을 추가하고 nextId 값에 1을 더해줍니다.
text
}
});
export const toggleTodo = id => ({
type: TOGGLE_TODO,
id
});
/* 초기 상태 선언 */
// 리듀서의 초기 상태는 꼭 객체타입일 필요 없습니다.
// 배열이여도 되고, 원시 타입 (숫자, 문자열, 불리언 이여도 상관 없습니다.
const initialState = [
/* 우리는 다음과 같이 구성된 객체를 이 배열 안에 넣을 것입니다.
{
id: 1,
text: '예시',
done: false
}
*/
];
export default function todos(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return state.concat(action.todo);
case TOGGLE_TODO:
return state.map(
todo =>
todo.id === action.id // id 가 일치하면
? { ...todo, done: !todo.done } // done 값을 반전시키고
: todo // 아니라면 그대로 둠
);
default:
return state;
}
}
루트 리듀서로 두 모듈을 합치기
- 리듀서를 합치는 작업은 리덕스가 제공하는
combineReducers
함수를 사용한다.
modules/index.js
import { combineReducers } from 'redux';
import counter from './counter';
import todos from './todos';
const rootReducer = combineReducers({
counter,
todos
});
export default rootReducer;
리듀서를 합쳤으면, 이를 이용하여 src디렉터리의 index.js에서 리덕스 스토어를 만들어 준다.
리덕스 스토어 생성 및 접근
- 리덕스에서 제공하는
createStore()
함수에 루트 리듀서를 파라미터로 넣어서 생성한다. - App 컴포넌트를 Provider라는 컴포넌트로 감싸고 props로 store를 넣어줘서 모든 컴포넌트에서 리덕스 스토어에 접근할 수 있도록 한다.
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {createStore} from "redux";
import rootReducer from "./modules";
import {Provider} from "react-redux";
const root = ReactDOM.createRoot(document.getElementById('root'));
const store = createStore(rootReducer); // 리덕스 스토어 생성
root.render(
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
반응형