월요일 말도 안돼
그래서 redux 왜 쓰는진 알았는데 어떻게 쓰냐구요? 알려드릴게요
얘네들을 이해하면 됩니다.
하나하나 알아봅시다.
redux store에서 모든 state와 state의 변경을 관리한다고 했었지 않습니깡.
좀 더 정확히 이야기하면 이렇습니다.
리듀서 함수: state 변경할 수 있는 권한을 가지고 있는 유일한 함수.
컴포넌트들: "리듀서님 state 좀 이렇게 이렇게 변경해주세요!" 하고 요청.
근데 리듀서 함수는 엄격한 친구라 아무렇게나 요청하면 요청을 받아주지 않는다.
액션 객체라는 형식을 지켜서 요청해야 받아줌
보통 이렇게 구성이 되어 있다.
하나하나 살펴보자. 카운터 예제가 가장 간단하므로 카운터 예제로 살펴보쟈.
(참고로 이렇게 리듀서와 액션 관련 코드들을 하나의 파일에 작성하는 방식을 Ducks 패턴이라고 부른다.)
// 액션 타입
const INCREASE_NUMBER = "counter/INCREASE_NUMBER";
const DECREASE_NUMBER = "counter/DECREASE_NUMBER";
// 액션 생성 함수
export const increase = () => {
return {
type: INCREASE_NUMBER;
}
};
export const decrease = () => {
return {
type: DECREASE_NUMBER;
}
};
// 리듀서 함수
export default function counter(state={number:0}, action){
switch(action.type) {
case INCREASE_NUMBER:
return {
...state,
number: number+1
};
case DECREASE_NUMBER:
return {
...state,
number: number-1
};
default:
return state;
}
}
위에서 언급한 것처럼, 일종의 요청서 혹은 주문서라고 생각하면 된다.
컴포넌트가 액션 객체라는 요청서에 "state를 이렇게 변경해줘~"라는 요청을 적어서 리듀서 함수에게 전송하는 거다.
이 요청서에 적어 보내야 리듀서가 그 요청을 들어준다.
액션 객체는 보통 이렇게 생겼다.
{type: 액션 타입명, payload: 같이 보내고싶은 데이터}
여기서 type은 필수고, 데이터는 옵션이다. (데이터 이름이 꼭 payload일 필요는 없다. 여러 개를 보낼 수도 있다.)
예를 들어,
{type: "increase_number", amount: 2}
// amount만큼 카운터를 증가시켜주세요!
이렇게 생긴 액션을 전달하면 리듀서 함수에서는 컴포넌트가 보낸 amount
라는 데이터값을 참조해서 카운터를 2만큼 증가시킬 수 있다.
state를 관리하고 변경하는 총 책임자.
컴포넌트들의 요청에 따라 state를 업데이트하고, 업데이트된 state를 리턴한다.
리듀서에는 액션별로 state를 업데이트하는 방법이 정의되어 있다.
위에 코드를 보면 switch문을 사용해 각 액션별로 state를 업데이트 하는 코드가 적혀있는 것을 볼 수 있다.
Ex INCREASE_NUMBER
라는 액션이 발생하면 number
라는 state를 1 증가시킨다.(state 변경)
모든 state 업데이트가 이 리듀서 함수에 정의되어 있는 방법대로 이루어진다.
redux store 내의 state를 업데이트 하려면 꼭 리듀서 함수를 거쳐야 함.
말그대로 파라미터를 받아서 액션 객체를 리턴해주는 함수다.
컴포넌트에서 좀 더 깔끔하게 액션을 발생시키기 위해 사용한다. (참고로 액션을 발생시킨다는 걸 "dispatch한다"고 한다.)
따라서 리듀서함수와 같은 파일에 export const
로 정의하고, 컴포넌트에서 import
해서 쓴다.
컴포넌트: 액션 수행에 필요한 데이터를 액션생성함수의 파라미터로 넘겨준다.
액션생성함수:{type: 액션명, payload: 컴포넌트가 넘겨준 데이터}
이렇게 생긴 액션객체를 리턴.
다시 컴포넌트: 액션생성함수가 리턴해준 액션객체로 액션을 dispatch
리듀서 함수 : 컴포넌트가 발생시킨 액션에 따라 state를 변경
꼭 액션함수를 써서 액션을 dispatch할 필요는 없다.
그냥 컴포넌트 내에서 이렇게 할 수도 있다.
dispatch({type: "increase_number", payload: 2})
근데 일단 보기에 좀 난잡하고, 매번 type 어쩌구 타이핑 하는 게 번거롭다.
무엇보다 비동기 작업이 필요할 때 그 작업을 액션생성함수 내에서 처리하는 경우가 많아서, 그냥 나는 이렇게 통일해서 쓴다.
다음 글에서는 redux 내에서 비동기 작업을 처리하는 방법에 대해 알아보겠다.