
1. Redux란?
Redux는 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너이다. 쉽게 생각하면 각 컴포넌트마다 관리했던 state값들을
전역에서 관리해주는것이라고 이해하면된다. 프로젝트를 진행하다보면 부모 컴포넌트에서 하위 컴포넌트에다가 state값들을
props로 타고 타고 넘겨주는걸 경험해봤을텐데 이를 하나의 store에다가 관리를 해 어디에서든 접근이 쉽게 만들어준다.
2. 리덕스 프로젝트 구조
└── redux
├── index.js // root reducer
├── counter.js // 기능 1
├── fetch.js // 기능 2
src파일에다가 redux폴더를 만들어주고 redux의 구성 요소인 Action Type, Action, Reducer 셋을 모두 하나의 파일 안에서 관리하는 패턴으로 구성해준다. 이를 Ducks pattern이라고 한다.

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from "redux";
import { Provider } from "react-redux";
import rootReducer from "./redux";
import FunctionCounter from './FunctionCounter';
import ClassCounter from './ClassCounter';
const store = createStore(rootReducer);
ReactDOM.render(
<Provider store={store}>
<ClassCounter/>
</Provider>
,document.getElementById('root')
);
기본적으로 src/index.js에서 가장 상위에다가 <Provider>태그로 감싸줘야한다. 그리고 store속성에다 위에서 변수 store을 달아준다.
// src/redux/index.js
import { combineReducers } from "redux";
import fetch from './fetch'
import counter from './counter';
const rootReducer = combineReducers({
fetch,
counter
});
export default rootReducer;
redux폴더안에 있는 index.js에서 rootReducer을 선언을 해주는데 이때 리덕스에서 제공해주는 combineReducers을 통해서
2개 이상의 Reducer들을 관리가 가능하다.
// src/redux/counter.js
const initialState = { count: 10};
const INCREASE = 'counter/INCREASE'
const DECREASE = 'counter/DECREASE'
export const increase = () => ({ type: INCREASE });
export const decrease = () => ({ type: DECREASE });
export default function counter(state = initialState, action) {
switch (action.type) {
case INCREASE:
return { count: state.count + 1 };
case DECREASE:
return { count: state.count - 1 };
default:
return state;
}
}
initialState라는 변수에다가 state를 관리하고(초기 상태 선언) , INCREASE, DECREASE는 액션 타입을 만드는 과정이다.
그 다음에 increase, decrease는 액션 생성함수를 선언한거다. 마지막으로 counter라는 리듀서를 생성한거다.
리듀서에서 액션 타입에 따라 어떤걸 실행할지 switch, case문으로 결정한다.
3. 함수형 컴포넌트에서 적용해보기
import React from 'react'
import { useDispatch, useSelector } from "react-redux";
import { increase, decrease } from './redux/counter';
const FunctionCounter = () => {
const counter = useSelector((store) => store.counter)
const dispatch = useDispatch();
return (
<div>
<h1>Hello Redux</h1>
<h2>{counter.count}</h2>
<button onClick={()=>{dispatch(increase())}}>+</button>
<button onClick={() => {dispatch(decrease())}}>-</button>
</div>
)
}
export default FunctionCounter
함수형 컴포넌트에서는 useSelector라는 hook을 사용해서 쉽게 리덕스의 state값에 조회할 수 있다. useDispatch hook을 통해서
액션을 실행 할 수 있게한다. 그래서 +버튼을 누르게되면 increase() 액션이 실행되고 type이 INCREASE이므로 count가 +1
되는걸 확인할 수 있다.
4. 클래스형 컴포넌트에서 적용하기
import React, { Component } from 'react'
import { connect } from 'react-redux';
import * as counterAction from './redux/counter'
class ClassComponent extends Component {
render() {
const {count, increase, decrease} = this.props
return (
<div className="ClassCounter">
<h1>Hello Redux</h1>
<h2>{count}</h2>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
)
}
}
const mapStateToProps = (state) => ({
count: state.counter.count
});
const mapDispatchToProps = (dispatch) => ({
increase: () => dispatch(counterAction.increase()),
decrease: () => dispatch(counterAction.decrease())
});
export default connect(mapStateToProps, mapDispatchToProps)(ClassComponent);
Class형에서는 hook을 지원하지 않기때문에 connect함수로 적용해야된다. mapStateToProps와 mapDispatchToProps로
각각 store에 저장되있는 state값과 dispatch()로 액션 실행 함수를 가져와야한다. 이값들은 해당 컴포넌트의 props로 전달해준다.
그래서 render함수 밑에 구조분해할당으로 값들을 받아온것을 볼 수 있다.
'React' 카테고리의 다른 글
React Img Slider 구현(useRef) (0) | 2022.03.13 |
---|---|
TIL 22 React ref (0) | 2021.11.21 |
TIL 21 리액트 Router Nav바 숨기기 (0) | 2021.11.19 |
TIL 20 리액트 함수형 컴포넌트(useState) (0) | 2021.11.18 |
TIL 19 Props로 받은값 State로 넘기기 (0) | 2021.11.10 |