side effect(fetch, API 등)를 최대한 배제하고 컴포넌트를 만든다
가짜데이터가 들어오더라도 컴포넌트는 표현할 수 있게 구현한다.
하지만 '로딩중' 화면처럼 불가피한 side effect가 발생할 수 있다.
예시로 로딩중은 전역 상태에 영향이 가기 때문에 전역 상태로 관리할 수 있다.
특정 컴포넌트 내에서 관리되는 상태
ex) form(input, select, redio button 등)
여러 컴포넌트나 프로덕트 전체에서 동시에 관리되는 상태
데이터 무결성 이란?
데이터의 정확성을 보장하기 위해 데이터 변경,수정 시 제한을 둠으로 안정성을 높여 데이터 상태들을 항상 옳게 유지하는 것
신뢰할 수 있는 단일 출처 (Single source of truth) 란?
동일 데이터는 항상 같은 출처에서 데이터를 가지고 온다
전역상태 저장소 제공
Props drilling (프로퍼티 내려꽂기) 이슈 해결
만약 A부터 I까지의 컴포넌트가 있다면, 중간의 C,G 등은 상태가 필요없어도 props 만들어서 자식에 넘겨주는 문제.
전역상태 저장소가 있다면 이러한 문제가 해결
반드시 필요한 것은 아니다.
사진출처 https://www.slideshare.net/binhqdgmail/006-react-redux-framework
JS application들의 state 상태를 관리하는 방법
React의 props로 계속 내려줬던 방법에서 => 모든 컴포넌트가 props 없이 state 변경할 수 있음
React, Vue, Angular 등 다양한 곳에서 사용 가능
React와 같이 사용해서 유명하지만, React만 의존하는 라이브러리 아님
데이터 단방향흐름
Action → Dispatch → Reducer → Store 순서
type
payload
// payload가 필요 없는 경우
{ type: 'INCREASE' }
// payload가 필요한 경우
{ type: 'SET_NUMBER', payload: 5 }
Action 객체를 생성하는 함수로 사용
// payload가 필요 없는 경우
const increase = () => {
return {
type: 'INCREASE'
}
}
// payload가 필요한 경우
const setNumber = (num) => {
return {
type: 'SET_NUMBER',
payload: num
}
}
const deleteNumber = (id) => {
return {
type: 'DELETE_NUMBER',
payload: {
id,
}
}
Reducer로 Action을 전달해주는 함수
// Action 객체를 직접 작성하는 경우
dispatch( { type: 'INCREASE' } );
dispatch( { type: 'SET_NUMBER', payload: 5 } );
// 액션 생성자(Action Creator)를 사용하는 경우
dispatch( increase() );
dispatch( setNumber(5) );
Dispatch에서 전달받은 Action객체의 type값에 따라서 상태 변경하는 함수
const count = 1
// Reducer 생성 시 초기 상태를 인자로 요구.
const counterReducer = (state = count, action) {
// action.type값에 따라 분기하는 switch 조건문
switch (action.type)
//action.type === 'INCREASE'
case 'INCREASE':
return state + 1
// action.type === 'DECREASE'
case 'DECREASE':
return state - 1
// action.type === 'SET_NUMBER'
case 'SET_NUMBER':
return action.payload
// case가 없으면 기존 상태 리턴
default:
return state;
}
// Reducer 리턴 값 => 새로운 상태가 됨
// reducer.js
import { combineReducers } from 'redux';
const reducer1 = (initialState = [1, 2, 3], action) => {
...
};
const reducer2 = (initialState = {}, action) => {
...
};
const rootReducer = combineReducers({
counterReducer,
anyReducer,
...
});
전역 상태 저장소
import { createStore } from 'redux';
const store = createStore(rootReducer);
createStore에 마우스 호버 시 @deprecated
표시되어있다.
권장되진 않지만 사용을 금지하지는 않는다는 의미다.
: createStore 밑줄 그어진것은, @reduxjs/toolkit의 권장사용을 유도하기 위해서
configureStore
legacy_createStore
@deprecation 태그가 없는 동일한 기능 가장 간단한 옵션은 별칭 가져오기 이름 바꾸기를 수행하는 것입니다.{legacy_createStore as createStore} from "redux"
React에서 Redux 사용할때 활용하는 Hooks메서드
컴포넌트와 state와 연결하여 Redux의 state에 접근하는 메서드
// Redux Hooks 메서드는 'redux'가 아니라 'react-redux'에서 불러옵니다.
import { useSelector } from 'react-redux'
const counter = useSelector(state => state.counterReducer)
console.log(counter) // 1
Action 객체를 Reducer로 전달하는 메서드
이벤트 핸들러내에서 action 객체를 담아서 전달
import { useDispatch } from 'react-redux'
const dispatch = useDispatch()
dispatch( increase() )
console.log(counter) // 2
dispatch( setNumber(5) )
console.log(counter) // 5
Single source of truth
동일한 데이터는 항상 같은 곳에서 가지고 와야 한다는 의미입니다. 즉, Redux에는 데이터를 저장하는 Store라는 단 하나뿐인 공간이 있음과 연결이 되는 원칙입니다.
State is read-only
상태는 읽기 전용이라는 뜻으로, React에서 상태갱신함수로만 상태를 변경할 수 있었던 것처럼, Redux의 상태도 직접 변경할 수 없음을 의미합니다. 즉, Action 객체가 있어야만 상태를 변경할 수 있음과 연결되는 원칙입니다.
Changes are made with pure functions
변경은 순수함수로만 가능하다는 뜻으로, 상태가 엉뚱한 값으로 변경되는 일이 없도록 순수함수로 작성되어야하는 Reducer와 연결되는 원칙입니다.