16. 리덕스 라이브러리 이해하기

히치키치·2022년 1월 8일
0

React_Advance

목록 보기
6/9
post-thumbnail

✔ 개념

1. 액션

상태에 어떠한 변화가 필요하면 발생
액션 객체
: type 필드 필수 (액션 이름)
: 그 외 값은 상태 업데이트 시 참고

// 액션 객체 예시
{
  type: "ADD_TODO",
  data:{
          id:1,
          text:"리덕스 배우기"}
}

2. 액션 생성 함수

액션 객체 만드는 함수
변화 발생시키기 위해 액션 객체 만들어야 함
이를 매번 작성하는 번거로움 피하기 위해 함수 만들어 관리

function addTodo(data){
	return{
    	type:"ADD_TODO",
      	data
    };
}

//화살표 함수 사용
const changeInput=text=>({
  type: :"CHANGE_INPUT",
  text
})

3. 리듀서

변화를 일으키는 함수
액션 만들어 발생 시 리듀서는 현재 상태전달받은 액션 객체 파라미터로 받음
두 파라미터를 참고해 새로운 상태 만들어 반환

//리듀서 코드 예시
const initialState={
  counter:1
};
function reducer(state=initialState,action){
  	//현재 상태와 전달 받은 액션 객체
	switch(action.type){
        //전달 받은 액션에 맞는 새로운 상태 만들어 반환
      case INCREMENT:
        return{
        	counter:state.counter+1
        };
      default:
        return state;
    }
}

4. 스토어

한 개의 프로젝트에는 단 하나의 스토어를 만들어 리덕스를 적용
현재 어플리케이션 상태리듀서 있음

5. 디스패치

스토어의 내장 함수 중 하나로 액션을 발생시킴
dispatch(action 객체 파라미터)로 호출해 리듀서 함수 실행시켜 새로운 상태 만듦

6. 구독

스토어의 내장 함수 중 하나
subscribe(리스너 함수 파라미터)로 호출하면 해당 리스너 함수가 액션이 디스패치되어 상태가 업데이트될 때마다 호출됨

//subscribe 함수 예시
const listener=()=>{
  console.log("상태 업데이트됨");
}
const unsubscribe=store.subscribe(listener);
unsubscribe(); // 추후 구독을 비활성화할 때 함수 호출

✔ 바닐라 js로 리덕스 사용

1. Parcel로 프로젝트 생성 & UI 구성

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

2. DOM 레퍼런스 만들기

별도의 라이브러리 사용 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");

3. 액션 타입 & 액션 생성 함수 정의

액션
: 프로젝트 상태에 변화 일으킴
: 이름은 문자열 형태로, 주로 대문자로 작성하며 고유해야 함

액션 생성 함수
: 액션 객체는 반드시 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 });

4. 초깃값 설정

초기값 형태 자유

index.js

(...)

//초기 값 설정
const initialState = {
  toggle: false,
  counter: 0,
};

5. 리듀서 함수 정의

변화를 일으키는 함수로 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;
  }
}

6. 스토어 만들기

리덕스에서 createStore함수 불러옴
리듀서 함수를 스토어 생성 함수에 파라미터로 넣어줘야 함

index.js

import { createStore } from "redux";

(...)

const store = createStore(reducer);

7. render 함수 만들기

상태 업데이트될 때마다 호출되며 리액트와 달리 이미 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();

8. 구독하기

스토어 내장 함수 subscribe 사용
스토어 상태가 바뀔 때마다 render 함수가 호출되도록 함
subscribe 함수 파라미터로 함수 형태의 값을 전달
전달된 함수는 액션 발생해 상태 업데이트될 때마다 호출됨
(리액트에서는 react-redux 라이브러리가 이 작업 수행해 직접 작성 필요 X)

index.js

(...)
render();
store.subscribe(render);

9. 액션 발생시키기

스토어 내장 함수 dispatch 사용해 파라미터로 액션 객체로 전달해 액션 발생시킴
DOM 요소에 클릭 이벤트 설정하고 이벤트 함수 내부에 dispatch 함수 사용해 액션을 스토어에 전달

index.js

(...)
divToggle.onclick = () => {
  store.dispatch(toggleSwitch());
};

btnIncrease.onclick = () => {
  store.dispatch(increase(1));
};

btnDecrease.onclick = () => {
  store.dispatch(decrease());
};

✔ 리덕스 3가지 규칙

1. 단일 스토어

하나의 어플리케이션에는 하나의 스토어 있음

2. 읽기 전용 상태

상태 업데이트 시 기존 객체는 건드리지 않고 새로운 객체 생성
내부적으로 데이터 변경을 얕은 비교검사를 통해 감지해야 하기 때문에 불변성을 유지해야 함

3. 리듀서는 순수한 함수

순수한 함수

  • 파라미터로 이전 상태와 액션 객체로 받는 리듀서 함수
  • 파라미터 이외 값에 의존 금지
  • 이전 상태 건들지 X, 변화를 준 새로운 상태 객체를 만들어 반환
  • 똑같은 파라미터로 리듀서 함수 호출 시 똑같은 결과 값 반환해야함

0개의 댓글