React 리덕스
리덕스는 리액트에서 가장 많이 사용하는 상태관리 라이브러리이다. 컴포넌트의 상태 업데이트 관련 로직을 다른 파일로 분리시켜서 더욱 효율적으로 관리할 수 있다.
따라서, 전역 상태를 관리할때 굉장히 유용하다곤... 하지만 전역상태기 때문에 남발하면 혼란을 가중 시킬 수도 있다고 생각한다.!!
여튼 단순 전역 상태 관리면 Context API만으로도 충분하고 프로젝트 규모가 커지면 리덕스를 사용하는게 좋다고한다.
또한 개발자 도구도 지원하며 미들웨어라는 기능을 제공하여 비동기 작업을 훨씬 효율적으로 관리할 수있게 해준다고 한다.
## 설치방법
$ yarn create react-app <project name>
$ cd <project name>
$ yarn add redux react-redux
리덕스를 주로 사용하는 패턴으로는 프리젠테이셔널 컴포넌트, 컨테이터 컨테이너를 분리한다.
- 프리젠테이셔널 컴포넌트: 받은 props를 그대로 뿌려주기만 하는 컴포넌트
- 컨테이너 컴포넌트: 리덕스와 연동되어 있는 컴포넌트로, 리덕스로 부터 상태를 받아오기도 하고 리덕스 스토어에 액션을 디스패치 시키기도 한다.
액션타입, 액션생성함수, 리듀서 함수를 기능별로 파일 하나에 몰아서 작성하는 패턴을 "Ducks 패턴"이라고 불린다. 그리고 Ducks 패턴을 사용하여 액션타입, 액션 생성함수, 리듀서를 작성한 코드를 "모듈" 이라고 불린다. (개인적으로 Ducks 패턴이 간결할 것으로 생각이든다. Redux가 커질수록 관리할 상태들이 많아진다고 생각하기 때문.. 즉 관리포인트가 늘어날 수 있어서 말이지..
리듀서를 여러개 만들었다면 createStore 함수를 사용하여 스토어를 만들 때 리듀서 하나만 사용해야 한다. 따라서 리듀서를 리덕스에서 제공해주는 combineReducers 라는 유틸 함수를 사용하여 하나로 합쳐줘야한다.
# Provider 컴포넌트를 사용하여 프로젝트에 리덕스 적용하기
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
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")
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
# 여러 리듀서함수를 하나로 합치기
import { combineReducers } from "redux";
import counter from "./counter";
import todos from "./todos";
const rootReducer = combineReducers({
counter,
todos,
});
export default rootReducer;
또, 디덕스와 연동하려면 react-redux에서 제공하는 connect 함수를 사용해야한다.
- connect(mapStateToProps, mapDispatchToProps) (연동할 컴포넌트)
- mapStateToProps: 리덕스 스토어 안에 상태를 컴포넌트의 props로 넘겨주기 위해 설정하는 함수
- mapDispatchToProps: 액션 생성함수를 컴포넌트의 props로 넘겨주기 위해 사용하는 함수
- connect 함수의 리턴 값에 타깃 컴포넌트로 파라미터로 넣고 함수를 실행시키면 리덕스와 연동된 컴포넌트가 만들어지게된다.
1. Action
- 상태 변화가 필요하면 액션이 발생한다.
- 액션은 객체로 표현되며 type 필드를 반드시 가지고 있어야한다. type이 액션 이름이라고 보면 된다.
- 액션 생성함수는 액션 객체를 만들어 주는 함수이다.
- 음... Vuex의 commit 함수의 첫 번째 인자값과 비슷해보임
2. Reducer
- 변화를 일으키는 함수(vuex의 commit 함수와 비슷?)
- 액션을 만들어서 발생시키면 리듀서가 현재 상태와 전달받은 액션 객체를 파라미터로 받아온다.
- 두 값을 참고하여 새로운 상태를 만들어서 반환해준다.
- 리듀서 함수는 순수 함수여야하고 이전 상태와 액션 객체를 파라미터로 받는다.
- 이전 상태는 절대 건드리면 안되고 변화를 준 새로운 상태 객체를 만들어서 반환한다.
3. Store
- 한 개 프로젝트에서 단 하나의 스토어만 가질 수 있음
- 현재 앱 상태와 리듀서가 들어있고 그 외에도 중요한 함수를 가지고 있다.
4. Dispatch
- 스토어의 내장함수중 하나로 디스패치는 '액션을 발생시키는 것' (이게.. vuex store 객체의dispatch이랑 비슷한듯)
- diapatch(action)과 같은 형태로 액션 객체를 파라미터로 넣어서 호출한다.
- 이 함수를 호출하면 스토어는 리듀서 함수를 실행시켜 새로운 상태를 만들어 준다.
5. subscribe
- 이 함수 안에 리스너 함수를 파라미터를 넣어서 호출해 주면, 리스너 함수가 액션이 디스패치되어 상태가 업데이트될 때 마다 호출 된다.
Action -> Dispatcher -> Reducer -> 새로운 상태 ?