상태에 변화가 필요하면 액션이 발생한다.
이는 하나의 객체로 표현된다.
type이란 필드를 가지고 있어야 한다.
{type:'CHANGE_INPUT', text:'안녕'}
액션 객체를 만들어 주는 함수
어떤 변화를 일으켜야 할 때마다 액션 객체를 만들기 귀찮아서 함수로 만들어서 관리한다.
function addTodo(data) {
return {
type:'CHANGE_INPUT', text:'안녕'
}}
const addTodo = data => (
{type:'CHANGE_INPUT', text:'안녕'})
변화를 일으키는 함수
액션을 만들어서 발생시키면 리듀서가 현재 상태와 전달받은 액션 객체를 파라미터로 받아오고
두 값을 참고해 새로운 상태를 만들어서 반환해준다.
const 초기값 = { counter:1}
function reducer(state= 초기값,action){
switch(action.type){
case INCREMENT:
return { counter: state.counter+1 }
default:
return state
}}
프로젝트에 리덕스를 적용하기 위해 스토어를 만든다.
한개의 프로젝트는 하나의 스토어만 가질 수 있다.
스토어에는 현재 어플 상태와 리듀서가 들어가 있을 수 있다.
액션을 발생 시키는 것 , 스토어의 내장 함수 중 하나
이 함수가 호출되면 스토어는 리듀서 함수를 실행시켜서 새로운 상태를 만들어 준다.
스토어의 내장 함수 중 하나
subscribe 함수 안에 리스너 함수를 파라미터로 넣어서 호출하면 이 리스너 함수가 액션이 디스패치되어 상태가 업데이트될 때마다 호출된다.
const listener = () =>{console.log('상태가 업데이트됨')}
const unsubscribe = store.subscribe(listener)
unscribe() ; 추후 구독 비활성화 할때 함수 호출
Parcel 설치하기
$ npm install -g parcel-bundler
$ mkdir vanilla-redux
$ cd vanilla-redux
package.json 파일 만들기
$ yarn init -y
$ parcel index.html
redux 모듈 설치하기
$ yarn add redux
<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>
.toggle {
border: 2px solid black;
width: 64px;
height: 64px;
border-radius: 32px;
box-sizing: border-box;
}
.toggle.active {
background: yellowgreen;
}
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를 기본값으로 사용
action의 type에 따라 다른 작업을 처리한다.
...state로 불변성 유지를 해준다.
function reducer(state=initialState,action){
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
}
}
import { createStore } from "redux"
(...)
const store = createStore(reducer)
상태가 업데이트 될 때마다 호출되며 리액트의 render 함수와는 다르게 이미 html을 사용하여 만들어진 UI의 속성을 상태에 따라 변경해준다.
subscribe 함수 → 스토어의 상태가 바뀔 때마다 방금 만든 render 함수가 호출되도록 해준다.
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())
}