React

[React] 리듀서 구조잡기

mhko411 2021. 7. 14. 22:53
728x90

여러 개의 상태관리와 유지보수를 쉽게하고 컴포넌트 별로 세분화하는 코드를 작성하기위해 리듀서도 세분화할 필요가 있다. 관리해야 할 상태과 적을 때는 상관없지만 관리해야 할 상태의 수가 많아질수록 액션과 리듀서를 나눴을 때 위와 같은 장점이 있을 것이다.


"+" 버튼을 눌렀을 때 숫자를 증가시키는 컴포넌트(Count)와 문자를 추가하는 컴포넌트(Text)를 생성하였다. 또한 이에 대한 액션과 리듀서를 분리하였다.

reducer 만들기

먼저 src/reducers 라는 폴더를 만들고 각각 Count, Text에 대한 리듀서를 생성한다. 각각 해당하는 컴포넌트에 대한 리듀서 역할을 한다.

// ./src/reducers/count.js
import { ADD_COUNT } from "../actions/count"
const INIT_STATE = {
    count : 0,
}

export const countReducer = (state=INIT_STATE, action) => {
    switch(action.type) {
        case ADD_COUNT:
            return {
                ...state,
                count : action.count
            }
        default:
            return state
    }
}
// ./src/reducers/text.js
import { ADD_WORD } from "../actions/text"

const INIT_STATE = {
    word: ''
}

export const textReducer = (state=INIT_STATE, action) => {
    switch(action.type) {
        case ADD_WORD:
            return {
                ...state,
                word : state.word.concat(action.word)
            }
        default:
            return state
    }
}

 

action 만들기

이제 dispatch를 실행할 액션을 컴포넌트 별로 만들어준다. 

// ./src/actions/count.js
export const ADD_COUNT = 'ADD_COUNT';

export const addCount = (count) => {
    return {
        type: ADD_COUNT,
        count: count + 1
    }
}
// ./src/actions/text.js
export const ADD_WORD = 'ADD_WORD';

export const addWord = (word) => {
    return {
        type: ADD_WORD,
        word
    }
}

 

store 만들기

이제 store를 생성하도록 한다. 이를 위해 분리된 reducer를 하나로 합쳐야 하며 "combineReducers"를 사용할 수 있다.

두 개의 reducer를 불러와 묶어주며 이를 createStore에 전달하여 store를 생성한다.

// ./src/store/index.js
import { createStore, combineReducers } from 'redux';
import { textReducer } from '../reducers/text';
import { countReducer } from '../reducers/count';

const rootReducer = combineReducers({
    textReducer,
    countReducer
})

const store = createStore(rootReducer)
export default store

이후 index.js를 통해 App과 store를 연결하여 각각의 컴포넌트에서 상태와 액션에 쉽게 접근할 수 있도록한다. 

// ./index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './store/index';


ReactDOM.render(
  <Provider store={store}>
  <App />
  </Provider>,
  document.getElementById('root')
);

 

컴포넌트에서 상태와 액션 가져오기

각각의 컴포넌트에서 상태와 액션을 가져오기 위해서 "react-redux"에서 제공하는 connect를 사용할 수 있다.

connect는 특정 함수에서 반환하는 상태와 액션을 컴포넌트에 전달하는 역할을 한다. connect의 인자에는 순서대로 상태와 액션에 관련된 함수를 전달하며, 상태에 대한 함수를 사용하지 않는다면 첫 번째 인자에 null을 전달한다.

mapStateToProps에서는 상태를 반환해준다. state를 통해 각각의 reducer를 통해 상태에 접근할 수 있다.

// ./components/Count.jsx
import React from 'react';
import { connect } from 'react-redux';
import { addCount } from '../actions/count';

function Count({count, addCount}) {
    
    function onClick() {
        addCount(count)
    }
    return (
        <div className="count">
            <h2>count: {count}</h2>
            <button onClick={onClick}>+</button>
        </div>
    )
}

function mapStateToProps(state) {
    return {
        count: state.countReducer.count
    }
}
function mapDispatchToProps(dispatch) {
    return {
        addCount: (count) => dispatch(addCount(count))
    }
}

export default connect(mapStateToProps, mapDispatchToProps) (Count)

 

'React' 카테고리의 다른 글

[React] JSX  (0) 2021.11.16
[React] Custom Hook  (0) 2021.10.10
[React] PropTypes 사용하기  (0) 2021.09.21
[React] 디자인 패턴 : Container - Presenter 패턴  (0) 2021.07.31
[React] Life Cycle  (0) 2021.07.23