Redux 공식문서
Redux 공식문서 - 실용가이드
codevolution - react-redux tutorial : 추천 유튜브 강의영상(완전기초~오)
스토어라는 가상공간에 데이터를 모아두어, 필요한 컴포넌트에서 데이터를 가져다 사용,변경 할수 있다.중간 컴포에게 데이터전달-전달-전달 하지 않고, 중앙관리되는 데이터를 가져다 씀으로서, 데이터 누락, 무한화면그리기 없이 깔꼼!
리덕스와 리액트 contextAPI는 언제 사용하면 좋을까?
리액트 contextAPI는 컨포넌트의 통합 데이터를 관리하는 경우,
리덕스는 서버에서 가져온 데이터로 새로운 결과물을 만드는 경우
참고 : DO IT! 리액트 프로그래밍 정석
$ npx create-react-app [프로젝트명] --template redux
리액트 프로젝트를 이제 시작하려 한다면! CRA(create-react-app) 과 템플릿 지정으로 리덕스를 시작할 수 있다. react-redux 플젝 고고!
혹은 이미 프로젝트를 진행중이며, 리덕스를 추가하고자 한다면 아래 모듈을 설치하자!
$ npm i redux
만약 리덕스를 프로젝트에 추가하려 한다면 위 npm 명령어를 통해 리덕스를 추가하여 사용한다.
$ npm i redux
$ npm i react-redux
리액트 프로젝트에 리덕스를 추가한다면 위 2개의 모듈 설치가 필요하다. react-redux
, redux
를 설치하자!
$ npm i -D redux-devtools
크롬브라우저 확장프로그램설치와 연동하기 위해 툴킷을 설치한다. 스토어 값이 바뀌는 상태를 쉽게 확인 할수 있다. 개발단계에서만 사용하기때문에 -D
옵션이 붙었다.
액션은 무슨일이 일어났는지 설명하는 평범한 자바스크립트 객체, 그냥 이름표라고 생각하면 쉽겠다!
.../actionTypes.js
파일에 액션을 지정하여두고, import
하여 사용한다.
// 액션 정의 : .../actionTypes.js
// 액션명은 대문자로 입력
export const ADD_TODO = 'ADD_TODO'
export const TOGGLE_TODO = 'TOGGLE_TODO'
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'
{
type : ADD_TODO,
text : 'build my first Redux app',
index : 33, // 고유인덱스를 사용하기도함.
}
// 액션을 사용할 곳
import { ADD_TODO, TOGGLE_TODO, SET_VISIBILITY_FILTER } from '경로/actionTypes'
액션을 반환하는 함수를 액션크리에이터라고 함
export function addTodo(text) {
return { type: ADD_TODO, text }
}
export function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
export function setVisibilityFilter(filter) {
return { type: SET_VISIBILITY_FILTER, filter }
}
액션(이름표)에 대한 리듀서(함수)를 실행하여 상태를 변경한다.
import * from './headerTypes' // 해더컴포넌트 액션타입 모두 불러오기
const initState = { // state의 초기화 설정
state01 : {},
state02 : "",
state03 : true,
stateData : [],
...
}
// 해더 컴포넌트용 리듀서 정의, 각각의 컴포넌트별 리듀서, 액션, 액션크리에이터를 각각 작성하여 RootReducer.js에서 통합하여 store에 적용한다.
const headerReducer = (state = initState, action) => {
switch (action.type) {
case ADD_TODO :
return {
// 기존 state를 변경하지 않기위해 전개연산자
//or object.assign()사용하여 복사본생성
...state,
addTodo : action.payload.addTodo
}
case <액션타입명> :
return {
...state, // 누적 state
// 액션크리에이터함수 = action 자리에 오며, 인자로받은 state값이 적용
<stated이름> : action.payload.<state이름>
}
// 기본값 꼭 지정해주기
default :
return state
}
}
파일별 내용 정리
[컴포넌트명]Actions.js
: 액션타입 import, 액션크리에이터 정의[컴포넌트명]Types.js
: 액션타입 정의[컴포넌트명]Reducer.js
: 액선타입 import, state초기값설정, 액션에 따른 리듀서 정의(switch문)
combineReducers()
위 예제코드에서 본것 같이 각 컨포넌트별로 리듀서를 작성하거나, 또는 프로젝트 마다 특정 조건에 따라 분리하여 리듀서를 작성한다. 이럴때는 combineReducers()
함수를 통해 리듀서를 통합하여야 한다.
// .../rootReducer.js
import { combineReducers } from 'redux'
// 모든 리듀서 임포트
import 컴포1Reducer from './컴포1/컴포1Reducer'
import 컴포2Reducer from './컴포2/컴포2Reducer'
import 컴포3Reducer from './컴포3/컴포3Reducer'
import 컴포4Reducer from './컴포4/컴포4Reducer'
//
const rootReducer = combineReducers({
컴포1Reducer, // 여기에 컴포넌트리듀서 나열
컴포2Reducer,
컴포3Reducer,
컴포4Reducer,
})
export default rootReducer
위 예제코드에서는 rootReducer를 예로들었지만, 각 컴포넌트 리듀서에서 리듀서 함수를 나누어 작성할때도 combineReducers()를 통해 통합하여 export 할때 유용하다.
데이터가 저장되는 가상공간
store.js
파일을 만들어 스토어를 따로 관리하는 것이 좋다.combineReducers()
를 통해 통합된 rootReducer
준비npm i -S redux-devtools-extension
리덕스 데브툴 사용할거면 설치// 스토어생성기, 미들웨어적용 모듈 임포트
import { createStore, applyMiddleware } from 'redux';
// 여기서 부터 미들웨어/데브툴 관련 임포트
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
// 루트 리듀서 임포트
import rootReducer from './rootReducer';
// 스토어 생성
const store = createStore(
rootReducer, // 리듀서 연결
initState, // 상태 초기값
composeWithDevTools(applyMiddleware(thunk, logger))
// 사용할 데브툴/미들웨어 연결
)
위와 같이 createStore(<루트리듀서>,<상태 초기값 지정>,<미들웨어들>)
를 통해 스토어를 생성한다.
composeWithDevTools()
composeWithDevTools(applyMiddleware(미들웨어1, 미들웨어2))
미들웨어 (middleware)
- redux-devtools
- redux-saga
- thunk
- logger
$ npm i -S redux-devtools-extension
$ npm i -S redux-thunk
$ npm i redux-logger