[리액트를 다루는 기술] 16장 리덕스 라이브러리 이해하기
-
리덕스 : 리액트 상태 관리 라이브러리
무엇이 장점?
- 컴포넌트 상태 업데이트 관련 로직을 다른 파일로 분리 -> 더욱 효율적으로 관리 가능
- 컴포넌트끼리 똑같은 상태를 공유해야할때 -> 여러 컴포넌트를 거치지 x
- 전역상태를 관리할 때 굉장히 효과적..!(Context API 보다 더욱 체계적으로 관리)
- 코드의 유지보수성을 높여줌, 작업효율 극대화
++ 편리한 개발자도구, 미들웨어 기능 제공 -> 비동기작업 효율적 관리 가능
-
실습진행
핵심키워드 알아보기 - Parcel로 프로젝트 구성 - 토글 스위치와 카운터 구현
16.1 개념 미리 정리하기
- 개념을 익혀보장 ^^~
16.1.1 액션
- 액션 : 상태에 어떠한 변화가 필요할때 발생, 하나의 객체로 표현
{
type: 'TOGGLE_VALUE'
data: {
id: 1,
text: '리덕스 배우기'
}
}
{
type: 'CHANGE_INPUT',
text: '안녕하세요'
}
- type : 액션의 이름
- 이외의 값 : 상태 업데이트시 참고, 커스텀 가능
16.1.2 액션 생성 함수
- 액션생성함수 : 액션객체를 만들어 주는 함수
function addTodo(data) {
return {
type: 'ADD_TODO',
data
};
}
// 화살표 함수로도 가능
const changeInput = text => {{
type: 'CHANGE_INPUT',
text
}};
- 액션객체 일일이 만들기 귀찮 -> 함수로 만들어 관리
16.1.3 리듀서
- 리듀서(reducer) : 변화를 일으키는 함수
- 액션 만들어 발생 -> 리듀서가 파라미터(현재상태, 전달받은액션객체)로 받음 -> 두 값을 참조 -> 새로운 상태로 만들어 반환
const initialState = {
counter: 1
};
function reducer(state = initialState, action){
switch(action.type){
return {
counter: state.counter + 1
};
default:
return state;
}
}
16.1.4 스토어
- 스토어(store) : 프로젝트에 리덕스를 적용하기 위해 만듬, 1프젝 1스토어 가능, 스토어 안에는 현재 어플리케이션 상태, 리듀서, 몇가지 내장함수가 들어가 있음
16.1.5 디스패치
- 디스패치(dispatch) : 스토어의 내장함수중 하나, 액션을 발생시키는 것, dispatch(action)과 같은 형태로 파라미터로 넣어 호출
16.1.6 구독
- 구독(subscribe) : 스토어의 내장함수중 하나
- subscribe 함수내 리스너 함수를 파라미터로 호출시 -> 액션이 디스패치됨 -> 상태가 업데이트 될때마다 호출
const listener = () => {
console.log(‘상태가 업데이트됨‘);
}
const unsubscribe = store.subscribe(listener);
unsubscribe(); // 추후 구독을 비활성화할 때 함수를 호출
16.2 리액트 없이 쓰는 리덕스
- 리덕스에 대해..
리액트에 종속되는 라이브러리가 x
리액트에서 사용하려고 만들어졌지만 다른 UI 라이브러리/프레임워크와 함께 사용 가능(angular-redux, ember redux, Vue, 바닐라(vanilla) 자바스크립트에서도 사용할 수 있음)
16.2.1 Parcel로 프로젝트 만들기
- parcel-bundler 설치
npm install -g parcel-bundler
- package.json 파일 생성
mkdir vanilla-redux
cd vanilla-redux
// package.json 파일을 생성합니다.
npm init -y
- index.html , index.js 각각 생성
<html>
<body>
<div>바닐라 자바스크립트</div>
<script src=”./index.js“></script>
</body>
</html>
console.log('hello parcel');
- 다음 명령어로 개발용 서버 실행하기(실행오류)
parcel index.html
- 리덕스 모듈설치
npm add redux
16.2.2 간단한 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 수정
<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>
16.2.3 DOM 레퍼런스 만들기
- DOM 직접 수정해야함 -> 별도의 라이브러리를 사용하지 않아서
- index.js
const divToggle = document.querySelector('.toggle');
const counter = document.querySelector('h1');
const btnIncrease = document.querySelector('#increase');
const btnDecrease = document.querySelector('#decrease');
16.2.4 액션 타입과 액션 생성 함수 정의
- 액션에 이름 정의 -> 문자열 형태, 대문자, 고유한 특성
- 액션객체는 type 값을 반드시 갖고 있어야함
const divToggle = document.querySelector('.toggle');
const counter = document.querySelector('h1');
const btnIncrease = document.querySelector('#id');
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 });
// 액션객체는 type 값을 반드시 갖고 있어야함
16.2.5 초깃값 설정
- 초깃값의 형태는 자유(숫자, 문자열, 객체 등)
- index.js 수정
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
};
16.2.6 리듀서 함수 정의
- 리듀서 : 변화를 일으키는 함수
- state와 action 값을 받아옴
- index.js 수정
const divToggle = document.querySelector('.toggle');
const counter = document.querySelector('h1');
const btnIncrease = document.querySelector('#id');
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) {
// 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;
}
}
16.2.7 스토어 만들기
- createStore 함수 사용 -> 리덕스에서 해당 함수를 불러옴, 함수 파라미터에는 리듀서 함수를 넣어줌
import { createStore } from 'redux';
(...)
const store = createStore(reducer);
16.2.8 render 함수 만들기
- render 함수 : 상태가 업데이트 될때마다 호출
- index.js 수정
(...)
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();
16.2.9 구독하기
- 스토어 상태 바뀔때마다 render 함수 호출되게 하기
- subscribe 함수의 파라미터로는 함수 형태의 값을 전달해 줌
- 나중에는 사용 xs
컴포넌트에서 리덕스 상태를 조회하는 과정에서 react-redux라는 라이브러리가 이 작업을 대신해 주기 때문
(...)
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);
16.2.10 액션 발생시키기
- 디스패치 : 액션을 발생시키는 것
- index.js 수정
(...)
divToggle.onclick = () => {
store.dispatch(toggleSwitch());
};
btnIncrease.onclick = () => {
store.dispatch(increase(1));
};
btnDecrease.onclick = () => {
store.dispatch(decrease());
};
16.3 리덕스의 세 가지 규칙
16.3.1 단일 스토어
- 상태관리가 복잡해질수 있으므로 권장 x
16.3.2 읽기 전용 상태
- 리덕스도 리액트 처럼 불변성을 지켜주어야함
- 상태를 업데이트할 때 기존의 객체는 건드리지 않고 새로운 객체를 생성해 주어야 함
- WHY? 내부적으로 데이터가 변경되는 것을 감지하기 위해 얕은 비교(shallow equality) 검사를 하기 때문
16.3.3 리듀서는 순수한 함수
- 순수한 함수의 조건
- 리듀서 함수는 이전 상태와 액션 객체를 파라미터로 받음
- 파라미터 외의 값에는 의존하면 x
- 이전 상태는 절대로 건드리지 않고, 변화를 준 새로운 상태 객체를 만들어서 반환
- 똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과 값을 반환해야함
Author And Source
이 문제에 관하여([리액트를 다루는 기술] 16장 리덕스 라이브러리 이해하기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@uiop01900/리액트를-다루는-기술-16장-리덕스-라이브러리-이해하기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)