상태에 어떠한 변화가 필요하면 발생
액션 객체
: type 필드 필수 (액션 이름)
: 그 외 값은 상태 업데이트 시 참고
// 액션 객체 예시
{
type: "ADD_TODO",
data:{
id:1,
text:"리덕스 배우기"}
}
액션 객체 만드는 함수
변화 발생시키기 위해 액션 객체 만들어야 함
이를 매번 작성하는 번거로움 피하기 위해 함수 만들어 관리
function addTodo(data){
return{
type:"ADD_TODO",
data
};
}
//화살표 함수 사용
const changeInput=text=>({
type: :"CHANGE_INPUT",
text
})
변화를 일으키는 함수
액션 만들어 발생 시 리듀서는 현재 상태와 전달받은 액션 객체 파라미터로 받음
두 파라미터를 참고해 새로운 상태 만들어 반환
//리듀서 코드 예시
const initialState={
counter:1
};
function reducer(state=initialState,action){
//현재 상태와 전달 받은 액션 객체
switch(action.type){
//전달 받은 액션에 맞는 새로운 상태 만들어 반환
case INCREMENT:
return{
counter:state.counter+1
};
default:
return state;
}
}
한 개의 프로젝트에는 단 하나의 스토어를 만들어 리덕스를 적용
현재 어플리케이션 상태와 리듀서 있음
스토어의 내장 함수 중 하나로 액션을 발생시킴
dispatch(action 객체 파라미터)로 호출해 리듀서 함수 실행시켜 새로운 상태 만듦
스토어의 내장 함수 중 하나
subscribe(리스너 함수 파라미터)로 호출하면 해당 리스너 함수가 액션이 디스패치되어 상태가 업데이트될 때마다 호출됨
//subscribe 함수 예시
const listener=()=>{
console.log("상태 업데이트됨");
}
const unsubscribe=store.subscribe(listener);
unsubscribe(); // 추후 구독을 비활성화할 때 함수 호출
npm install -g parcel-bundler
mkdir vanilla-redux
cd vanilla-redux
//package.json 파일 생성
yarn init-y
index.css
.toggle {
border: 2px solid black;
width: 64px;
height: 64px;
border-radius: 32px;
box-sizing: border-box;
}
.toggle.active {
background: yellow;
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="index.css" />
</head>
<body>
<div class="toggle"> </div>
<hr/>
<h1>0</h1>
<button id="increase">+1</button>
<button id="decrease">-1</button>
<script src="./index.js"></script>
</html>
리덕스 모듈 설치
yarn add redux
서버 실행
parcel index.html
별도의 라이브러리 사용 X하여 DOM 직접 수정 필요
index.js
//DOM 레퍼런스 만들기
//수정할 DOM 노드를 가리키는 값 미리 선언
const divToggle = document.querySelector(".toggle");
const counter = document.querySelector("h1");
const btnIncrease = document.querySelector("#increase");
const btnDecrease = document.querySelector("#decrease");
액션
: 프로젝트 상태에 변화 일으킴
: 이름은 문자열 형태로, 주로 대문자로 작성하며 고유해야 함
액션 생성 함수
: 액션 객체는 반드시 type 가짐
: 추가적으로 상태 업데이트 시 참고하고 싶은 값 넣으면 됨
index.js
//DOM 레퍼런스 만들기
(...)
//액션 생성
const TOGGLE_SWITCH = "TOGGLE_SWITCH";
const INCREASE = "INCREASE";
const DECREASE = "DECREASE";
//액션 생성 함수 생성
const toggleSwitch = () => ({ type: TOGGLE_SWITCH });
const increase = (difference) => ({ type: INCREASE, difference });
const decrease = () => ({ type: DECREASE });
초기값 형태 자유
index.js
(...)
//초기 값 설정
const initialState = {
toggle: false,
counter: 0,
};
변화를 일으키는 함수로 state와 action을 파라미터로 받아옴
: 리듀서 함수가 처음 호출될 때는 state 값이 undefined로 해당 값이 initalState를 기본값으로 설정되도록 파라미터 설정함
: spread 연산자(...) 사용해 상태의 불변성 유지하며 업데이트함
(복잡한 객체 구조나 배열 다루는 경우 immer 라이브러리 사용)
index.js
(...)
//state가 undefined일 때 initialState 기본값으로 사용
function reducer(state = initialState, action) {
//action.type에 따라 다른 작업 처리
switch (action.type) {
case TOGGLE_SWITCH:
return {
...state,
toggle: !state.toggle,
};
case INCREASE:
return {
...state,
counter: state.counter + action.difference,
};
case DECREASE:
return {
...state,
counter: state.counter - 1,
};
default:
return state;
}
}
리덕스에서 createStore함수 불러옴
리듀서 함수를 스토어 생성 함수에 파라미터로 넣어줘야 함
index.js
import { createStore } from "redux";
(...)
const store = createStore(reducer);
상태 업데이트될 때마다 호출되며 리액트와 달리 이미 html 사용해 만들어진 UI 속성을 상태에 따라 변경됨
index.js
import { createStore } from "redux";
(...)
const store = createStore(reducer);
const render = () => {
//현재 상태 불러옴
const state = store.getState();
//토글 처리
if (state.toggle) {
divToggle.classList.add("active");
} else {
divToggle.classList.remove("active");
}
//카운터 처리
counter.innerText = state.counter;
};
render();
스토어 내장 함수 subscribe 사용
스토어 상태가 바뀔 때마다 render 함수가 호출되도록 함
subscribe 함수 파라미터로 함수 형태의 값을 전달함
전달된 함수는 액션 발생해 상태 업데이트될 때마다 호출됨
(리액트에서는 react-redux 라이브러리가 이 작업 수행해 직접 작성 필요 X)
index.js
(...)
render();
store.subscribe(render);
스토어 내장 함수 dispatch 사용해 파라미터로 액션 객체로 전달해 액션 발생시킴
DOM 요소에 클릭 이벤트 설정하고 이벤트 함수 내부에 dispatch 함수 사용해 액션을 스토어에 전달
index.js
(...)
divToggle.onclick = () => {
store.dispatch(toggleSwitch());
};
btnIncrease.onclick = () => {
store.dispatch(increase(1));
};
btnDecrease.onclick = () => {
store.dispatch(decrease());
};
하나의 어플리케이션에는 하나의 스토어 있음
상태 업데이트 시 기존 객체는 건드리지 않고 새로운 객체 생성
내부적으로 데이터 변경을 얕은 비교검사를 통해 감지해야 하기 때문에 불변성을 유지해야 함
순수한 함수