본문 바로가기

React/Redux

[React] Redux #3 | 리덕스 모듈 만들기

리액트 프로젝트에 리덕스를 적용하기 위한 리덕스 모듈을 만들어보자!

 

💡리덕스 모듈?

  • 다음 항목들이 모두 들어있는 자바스크립트 파일
    1. 액션 타입
    2. 액션 생성함수
    3. 리듀서
  • 위 항목들을 리덕스를 사용하기 위해 각각 다른 파일에 저장할 수도 있다.
  • 액션과 리듀서가 서로다른 파일에 정의되어 있을 수도 있지만, 개발하는데 꽤나 불편할 수도 있으므로 리듀서와 액션 관련 코드들을 하나의 파일에 몰아서 작성해보자! (Duck 패턴)

 

1️⃣ counter 모듈 만들기

  • 첫번째 모듈, 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;
      }   
}

 

2️⃣ 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;
  }
}

 

3️⃣ 루트 리듀서 만들기

현재 counter, todos 두가지 리덕스 모듈을 만들었다.

한 프로젝트에 여러개의 리듀서가 있을 때는 한 리듀서(루트 리듀서)로 합쳐서 사용!

 

💡combineReducers 함수

  • 리듀서를 합치는 작업
  • 리덕스 내장 함수

modules/index.js

import { combineReducers } from 'redux';
import counter from './counter';
import todos from './todos';

const rootReducer = combineReducers({
    counter,
    todos
});

export default rootReducer;

 

4️⃣ 스토어 만들기

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { createStore } from 'redux';
import rootReducer from './modules';

const store = createStore(rootReducer); // 스토어를 만듭니다.
console.log(store.getState()); // 스토어의 상태를 확인해봅시다.

ReactDOM.render(<App />, document.getElementById('root'));

결과

상태가 잘 출력된 것을 확인했으면, console.log(store.getState()); 지워주기

 

 

5️⃣ 리액트 프로젝트에 리덕스 적용하기

  • react-redux 라이브러리 설치
yarn add react-redux

 

  • index.js에서 Provider라는 컴포넌트를 불러와서 App컴포넌트 감싸기
  • 그리고 Provider의 props에 store 넣어주기
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import { createStore } from 'redux';
    import { Provider } from 'react-redux';
    import rootReducer from './modules';
    
    const store = createStore(rootReducer); // 스토어를 만듭니다.
    
    ReactDOM.render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('root')
    );​
  • Provider로 store을 넣어서 App 을 감싸면 우리가 렌더링 하는 그 어떤 컴포넌트 던지 리덕스 스토어에 접근 가능!

 

 


Reference

벨로퍼트의 모던 리액트