Redux 정리(1)
리덕스 개념 정리
추리고 추린 redux 정리!!
제 생각에 중요하다고 생각되는 부분들만 넣었습니다! 추가적으로 어렵거나 없는 부분이 있는경우에는 따로 찾아보셔서 공부하시는게 좋을 거 같습니다!
액션(Action)
상태에 어떤 변화가 필요할시에 액션이 발생한다
즉, 말 그대로 어떤 행동이 벌어지는 것
사용법
{
type: 'TOGGLE_VALUE'
}
액션 객체: 반드시 type 필드 가져야 한다.
type 외의 값들은 ,나중에 state를 업데이트 할때 참고하면 되는 값들이다
예제
{
type: 'ADD_TODO',
data: {
id: 1,
text: '리덕스 배우기'
}
}
//이러한 하나의 객체를 액션이라고 칭한다
//즉, 어떠한 행동을 하기 위해
액션 생성 함수
액션 객체를 만들어 주는 함수
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) {
case INCREMENT:
return {
counter: state.counter + 1
};
default:
return state;
}
}
16.1.4 스토어
스토어:프로젝트에 리덕스를 적용하기 위함
한개의 프로젝트는 하나의 스토어만 가질 수 있다.
스토어 안에는 현재 애플리케이션 상태, 리듀서가 들어가 있으며, 몇가지 중요한 내장 함수를 지닌다.
- 현재 애플리케이션 상태
- 리듀서
- 몇가지 중요한 내장함수
16.1.5 디스패치
디스패치:스토어의 내장 함수 중 하나, "액션을 발생시키는 것"
이 함수는 dispatch(action)과 같은 형태로 액션 객체를 파라미터로 넣어 호출
디스패치 함수 호출→스토어에서 리듀서 함수 실행→ 새로운 상태(new state)를 만든다
16.1.6 구독
스토어의 내장 함수 중 하나.
subscribe 함수 안에 리스너 함수를 파라미터로 넣어서 호출해 주면, 이 리스너 함수가 액션이 디스패치되어 상태가 업데이트될때마다 호출
const listener = () => {
console.log(‘상태가 업데이트됨‘);
}
const unsubscribe = store.subscribe(listener);
unsubscribe(); // 추후 구독을 비활성화할 때 함수를 호출
16.2 리액트 없이 쓰는 리덕스
16.2.1 Parcel로 프로젝트 만들기
parcel:쉽고 빠르게 웹 애플리케이션 프로젝트 구성 가능
$ yarn global add parcel-bundler
16.2.2 간단한 UI 구성
.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 레퍼런스 만들기
이번 프로젝트에서는 UI를 관리할 때 별도의 라이브러리를 사용하지 않기 때문에 DOM을 직접 수정해 주어야 합니다
다음과 같이 자바스크립트 파일 상단에 수정할 DOM 노드를 가리키는 값을 미리 선언
index.js
const divToggle = document.querySelector(‘.toggle‘);
const counter = document.querySelector(‘h1‘);
const btnIncrease = document.querySelector(‘#increase‘);
const btnDecrease = document.querySelector(‘#decrease‘);
querySelector 사용이유:
getElementById()를 사용하면 ID 속성으로 밖에 객체를 선택하지 못한다
따라서 주로 querySelector()를 사용, html의 태그,class,id 모두 js에서 가져온다
그로인해 html 요소들을 JavaScript에서 변경할 수 있다.
단! 첫번째 요소만 선택 가능하다.
16.2.4 액션 타입과 액션 생성 함수 정의
액션:프로젝트의 상태에 변화를 일으키는 것
리듀서:변화를 일으키는 함수(함수의 파라미터로 state,action 값을 받아 온다)
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) {
// action.type에 따라 다른 작업을 처리함
switch (action.type) {
case TOGGLE_SWITCH:
return {
…state, // 불변성 유지를 해 주어야 합니다.
toggle: !state.toggle //기본 상태는 false 이므로 true이다
};
case INCREASE:
return {
…state,
counter: state.counter + action.difference
//state.counter는 0, action.difference는 잘 모름
};
case DECREASE:
return {
…state,
counter: state.counter - 1
};
default:
return state;
}
}
리듀서 함수가 맨 처음 호출될 때는 state 값이 undefined입니다. 해당 값이 undefined로 주어졌을 때는 initialState를 기본값으로 설정하기 위해 함수의 파라미터 쪽에 기본값이 설정되어 있습니다.
리듀서에서는 상태의 불변성을 유지하면서 데이터에 변화를 일으켜 주어야 합니다
이때 spread 연산자를 사용하면 편하다
단, 객체의 구조가 복잡해지면 spread 연산자로 불변성을 관리하며 업데이트 하는 것이 어려울 수 있으므로, 리덕스의 상태는 최대한 깊지 않은 구조로 진행하는 것이 좋다.
객체의 구조가 복잡해지거나 배열도 함께 다루는 경우 immer 라이브러리를 사용하면 좀 더 쉽게 리듀서를 작성할 수 있다.
16.2.7 스토어 만들기
스토어를 만들 때는 createStore 함수를 사용한다.
함수의 파라미터에 reducer 함수를 넣어줘야 한다.
스토어를 만들면, 스토어의 내장함수를 사용할 수 있게 된다.
사용법
import { createStore } from 'redux';
(...)
const store = createStore(reducer);
16.2.8 render 함수 만들기
render함수:
상태가 업데이트 될 때마다 호출,
리액트의 render함수와는 다르게 이미 html을 사용하여 만들어진 UI의 속성을 상태에 따라 변경해준다.
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) {
// action.type에 따라 다른 작업을 처리함
switch (action.type) {
case TOGGLE_SWITCH:
return {
…state, // 불변성 유지를 해 주어야 합니다.
toggle: !state.toggle //기본 상태는 false 이므로 true이다
};
case INCREASE:
return {
…state,
counter: state.counter + action.difference
//state.counter는 0, 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();
*classList: 자바스크립트에서 클래스이름을 조작하는 것
16.2.9 구독하기
스토어의 상태가 바뀔 때마다 방금 만든 render 함수가 호출되도록 해줄 것이다.
이작업은 스토어의 내장 함수 subscribe를 사용하여 수행할 수 있다.
subscribe 함수의 파라미터로는 함수 형태의 값을 전달해준다.
예시)
const listener = () => {
console.log('상태가 업데이트됨');
}
const unsubscribe = store.subscribe(listener);
unsubscribe(); // 추후 구독을 비활성화할 때 함수를 호출
이번 프로젝트에서는 subscribe 함수를 직접 사용하지만, 추후 리액트 프로젝트에서 리덕스를 사용할 때는 이 함수를 직접 사용하지 않을 것입니다.
왜냐하면, 컴포넌트에서 리덕스 상태를 조회하는 과정에서 react-redux라는 라이브러리가 이 작업을 대신해 주기 때문입니다.
이제 상태가 업데이트 될 때마다 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);
16.2.10 액션 발생시키기
디스패치:액션을 발생시키는 것
스토어의 내장 함수인 dispatch를 사용
파라미터는 액션 객체를 넣어주면 된다.
다음과 같이 각 DOM 요소에 클릭 이벤트를 설정하세요. 이벤트 함수 내부에서는 dispatch 함수를 사용하여 액션을 스토어에게 전달해 주겠습니다.
(…)
divToggle.onclick = () => {
store.dispatch(toggleSwitch());
};
btnIncrease.onclick = () => {
store.dispatch(increase(1));
};
btnDecrease.onclick = () => {
store.dispatch(decrease());
};
16.3 리덕스의 3가지 규칙
16.3.1 단일 스토어
하나의 애플리케이션 ⇒ 하나의 스토어
16.3.2 읽기 전용 상태
리덕스 상태는 읽기 전용
기존에 리액트에서 setState를 사용하여 state를 업데이트할 때도 객체나 배열을 업데이트하는 과정에서 불변성을 지켜 주기 위해 spread 연산자를 사용하거나 immer와 같은 불변성 관리 라이브러리를 사용했지요?
리덕스도 마찬가지입니다. 상태를 업데이트할 때 기존의 객체는 건드리지 않고 새로운 객체를 생성해 주어야 합니다.
16.3.3 리듀서는 순수한 함수
변화를 일으키는 리듀서 함수는 순수한 함수여야 한다.
순수한 함수의 조건
- 리듀서 함수는 이전 상태와 액션 객체를 파라미터로 받습니다.
- 파라미터 외의 값에는 의존하면 안 됩니다.
- 이전 상태는 절대로 건드리지 않고, 변화를 준 새로운 상태 객체를 만들어서 반환합니다.
- 똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과 값을 반환해야 합니다.
Author And Source
이 문제에 관하여(Redux 정리(1)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@victor247/Redux-정리1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)