리덕스란?
- JavaScript(자바스크립트) 상태관리 라이브러리이다.
- Redux의 본질은 Node.js 모듈이다.
리덕스를 사용하는 이유?
- 컴포넌트의 상태 업데이트 관련 로직을 다른 파일로 분리시켜서 효율적으로 관리 가능
- 컴포넌트끼리 똑같은 상태를 공유해야 할 때도 여러 컴포넌트를 거치지 않고 손쉽게 상태 값을 전달하거나 업데이트할 수 있다.
리덕스의 세 가지 규칙
1. Single source of truth(단일 스토어)
- 하나의 애플리케이션 안에는 하나의 스토어가 있다.
- 동일한 데이터는 항상 같은 곳에서 가지고 온다.
- 스토어라는 하나뿐인 데이터 공간이 있다는 의미
2. State is read-only(읽기 전용 상태)
- 상태를 업데이트 할때는 기존의 객체는 건드리지 않고 새로운 객체를 생성해야 한다.
- 좋은 성능을 유지하기 위해 얕은 비교(shallow equality) 검사를 하는데, 이를 위해 불변성을 유지 해야함
- 때문에 리액트에서
setState
메서드를 사용해야만 상태변경이 가능하듯이, 리덕스에서도 액션이라는 객체를 통해서만 상태를 변경할 수 있다.
3. Changes are made with pure functions(리듀서는 순수함수로만 가능)
- 변화를 일으키는 리듀서 함수는 순수한 함수여야 한다.
- 순수한 함수의 조건
- 리듀서 함수는 이전 상태와 액션 객체를 파라미터로 받는다.
- 파라미터 외의 값에는 의존하면 안된다.
- 이전 상태는 절대로 건드리지 않고, 변화를 준 새로운 상태 객체를 만들어서 반환한다.
- 똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과 값을 반환해야 한다.
리덕스를 구성하는 키워드
액션
- 상태에 어떠한 변화가 필요하면 액션이 발생
- 액션은 자바스크립트 객체 형식으로 이루어져 있다.
{
type: 'TOGGLE_VALUE'
}
액션 객체는 type 필드를 반드시 가지고 있어야 한다.
type외의 값들은 상태 업데이트를 할때 참고해야 할 값이다.
{
type: 'USER',
data: {
id: 'LightSource',
text: '리덕스 공부중'
}
}
{
type: 'CHANGE_INPUT',
text: '안녕하세요'
}
액션 생성함수
- 액션 객체를 만들어 주는 함수
//일반형 함수
function learnRedux(data) {
return {
type: 'USER',
data: {
id: 1,
text: '리덕스 공부중'
}
};
}
//화살표 함수
const learnRedux = data => ({
type : 'USER',
data
})
리듀서(Reducer)
- 리듀서는 변화를 일으키는 함수
- 액션을 만들어서 발생시키면 현재상태와 전달 받은 액션객체를 파라미터로 받아온다.
- 두 값을 참고하여 새로운 상태를 만들어서 반환해준다.
const initialState = {
counter: 1
};
function reducer(state = initialState, action) {
switch (action.type) {
case INCREMENT:
return {
counter: state.counter + 1
};
default:
return state;
}
}
스토어(store)
- 프로젝트는 단 하나의 스토어만 가질수 있다.
- 스토어 안에는 현재 애플리케이션 상태와 리듀서가 들어가 있고, 내장함수를 제공한다.
- 컴포넌트에서 상태 정보가 필요할 때 스토어에 접근한다.
디스패치(dispatch)
- 스토어의 내장함수이다.
- 디스패치는 ‘액션을 발생 시켜 주는 것’으로 이해하면 된다
dispatch(action)
과 같은 형태로 액션 객체를 파라미터로 넣어서 호출
구독(subscribe)
- 스토어의 내장함수이다.
- subscribe 함수안에 리스너 함수를 파라미터로 넣어서 호출하면, 리스너 함수가 액션이 디스패치되어 상태가 업데이트될 때 마다 호출된다.
const listenner = () => {
console.log('상태가 업데이트됨');
}
const unsubscribe = store.subscribe(listenner);
unsubscribe(); // 구독을 비활성화할 때 해당 함수 호출
예시
import { createStore } from 'redux';
// createStore는 스토어를 만들어주는 함수입니다.
// 리액트 프로젝트에서는 단 하나의 스토어를 만듭니다.
/* 리덕스에서 관리 할 상태 정의 */
const initialState = {
counter: 0,
text: '',
list: []
};
/* 액션 타입 정의 */
// 액션 타입은 주로 대문자로 작성합니다.
const INCREASE = 'INCREASE';
const DECREASE = 'DECREASE';
const CHANGE_TEXT = 'CHANGE_TEXT';
const ADD_TO_LIST = 'ADD_TO_LIST';
/* 액션 생성함수 정의 */
// 액션 생성함수는 주로 camelCase 로 작성합니다.
function increase() {
return {
type: INCREASE // 액션 객체에는 type 값이 필수입니다.
};
}
// 화살표 함수로 작성하는 것이 더욱 코드가 간단하기에,
// 이렇게 쓰는 것을 추천합니다.
const decrease = () => ({
type: DECREASE
});
const changeText = text => ({
type: CHANGE_TEXT,
text // 액션안에는 type 외에 추가적인 필드를 마음대로 넣을 수 있습니다.
});
const addToList = item => ({
type: ADD_TO_LIST,
item
});
/* 리듀서 만들기 */
// 위 액션 생성함수들을 통해 만들어진 객체들을 참조하여
// 새로운 상태를 만드는 함수를 만들어봅시다.
// 주의: 리듀서에서는 불변성을 꼭 지켜줘야 합니다!
function reducer(state = initialState, action) {
// state 의 초깃값을 initialState 로 지정했습니다.
switch (action.type) {
case INCREASE:
return {
...state,
counter: state.counter + 1
};
case DECREASE:
return {
...state,
counter: state.counter - 1
};
case CHANGE_TEXT:
return {
...state,
text: action.text
};
case ADD_TO_LIST:
return {
...state,
list: state.list.concat(action.item)
};
default:
return state;
}
}
/* 스토어 만들기 */
const store = createStore(reducer);
console.log(store.getState()); // 현재 store 안에 들어있는 상태를 조회합니다.
// 스토어안에 들어있는 상태가 바뀔 때 마다 호출되는 listener 함수
const listener = () => {
const state = store.getState();
console.log(state);
};
const unsubscribe = store.subscribe(listener);
// 구독을 해제하고 싶을 때는 unsubscribe() 를 호출하면 됩니다.
// 액션들을 디스패치 해봅시다.
store.dispatch(increase());
store.dispatch(decrease());
store.dispatch(changeText('안녕하세요'));
store.dispatch(addToList({ id: 1, text: '와우' }));
정리
- 리덕스는 데이터가 한 방향으로 흘러가게 되어 있다.
Action(액션)
객체가dispatch()
메소드에 전달된다.dispatch(액션)
을 통해서Reducer
를 호출한다.Reducer
는 새로운State
를 생성한다.
참고
https://react.vlpt.us/redux/03-prepare.html
반응형