액션, 액션생성함수, 리듀서, 스토어, 디스패치, 구독 이런게 있습니다.
프로젝트를 만들면서 배워보겠습니다.
yarn global add parcel-bundler
mkdir banilla-redux
cd vanilla-redux
yarn init -y
<!-- index.html -->
<html>
<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>
</body>
</html>
// index.js
const divToggle = documnet.querySelector(".toggle");
const counter = documnet.querySelector(".hi");
const btnIncrease = documnet.querySelector("#increase");
const btnDecrease = documnet.querySelector("#decrease");
한번 실행해보고 redux를 다운받습니다.
pacel index.html
yarn add redux
간단한 UI를 구성해 보겠습니다.
// index.css
.toggle {
border: 2px solid black;
width: 64px;
height: 64px;
border-radius: 32px;
box-sizing: border-box;
}
.toggle.active {
background: yellow;
}
index.html 변경했습니다. (원이생겼습니다.)
리덕스 공부할 준비가 끝났습니다.
프로젝트의 상태에 변화를 일으키는 것을 액션이라고 합니다.
(액션은 객체로 표현됩니다.)
액션이름은 대문자로 해야합니다.
// index.js
const divToggle = documnet.querySelector(".toggle");
const counter = documnet.querySelector(".hi");
const btnIncrease = documnet.querySelector("#increase");
const btnDecrease = documnet.querySelector("#decrease");
// 액션이름을 추가
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 값을 받아옵니다
// index.js initialState 밑에 작성
// 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 false;
}
스토어에 리듀서를 넣어줍니다.
// index.js
import { createStore } from "redux";
(...)
const store = createStore(reducer);
render 함수를 작성해보겠습니다. 이 함수는 상태가 업데이트 될 때마다 호출되며, 리액트의 render 함수와는 다르게 UI의 상태에 따라 변경해줍니다.
스토어 밑에다가 아래 코드를 추가합니다.
//index.js
const render = () => {
const state = store.getState(); // 현재 상태를 불러옵니다
// 토글 처리
if (state.toggle) {
divToggle.classList.add("active");
} else {
divToggle.classList.remove("active");
}
// 카운터 처리
counter.innerText = state.counter;
};
render();
렌더함수는 현재 상태를 불러와 화면막 변경해줍니다.
아직 현재상태를 변경안해줬으니 클릭했을 때 값이 올라가진 않습니다.
스토어의 상태가 바뀔때마다 render 함수가 호출되도록 해줄것입니다.
스토어의 내장 함수 subscribe를 사용하여 수행할수 있습니다.
아 그냥 그래서 최종 코드가 아래에 있음
import { createStore } from "redux";
const divToggle = document.querySelector(".toggle");
const counter = document.querySelector("h1");
const btnIncrease = document.querySelector("#increase");
const btnDecrease = document.querySelector("#decrease");
// 액션이름을 추가
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 });
// 초기상태
const initialState = {
toggle: false,
counter: 0,
};
// state가 undefined 일 때는 initialState를 기본값을 사용
function reducer(state = initialState, action) {
console.log(action);
// action.type에 따라 다른 작업을 처리함
switch (action.type) {
case TOGGLE_SWITCH:
return {
...state, // 불변성 융지
toggle: !state.toggle,
};
case INCREASE:
console.log("일로 안들어오나?");
return {
...state, // 불변성 융지
counter: state.counter + action.difference, // 이건 뭐지?
};
case DECREASE:
return {
...state,
counter: state.counter - 1,
};
default:
return state;
}
}
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();
store.subscribe(render);
divToggle.onclick = () => {
store.dispatch(toggleSwitch());
};
btnIncrease.onclick = () => {
store.dispatch(increase(1));
};
btnDecrease.onclick = () => {
store.dispatch(decrease());
};
리덕스를 사용하니깐 간단한 어플도 복잡해졌다. 하..
정리를 해보자면
리듀서는 변화를 일으키는 함수입니다.
리듀서는 스토어 안에 넣어놓고
액션과 상태를 리듀서에 전달하기 위해 스토어에 넣어줍니다.(dispatch)
그럴려면 초기상태, 액션을 발생시키는 함수 가 필요합니다.
그냥 이렇게 상태를 관리하나 봅니다.. 휴
onClick 이벤트가 발생을 안하는것 같아요ㅠ
또한 콘솔에 이런 에러도 떠요 Uncaught TypeError: Cannot set property 'innerText' of nullㅠ