원래의 상태(state)는 최상위 컴포넌트에 위치시키는게 적절하지만, 프로젝트 규모가 커지거나 코드 관리를 용이하게 하기위해서는 Redux 같은 상태관리 툴을 이용할 수 있다.
1️⃣ 상태가 변경되어야 하는 이벤트가 발생하면, 변경될 상태에 대한 정보가 담긴 Action 객체
가 생성된다.
2️⃣ 이 Action 객체는 Dispatch 함수
의 인자로 전달된다.
3️⃣ Dispatch 함수는 Action 객체를 Reducer 함수
로 전달해준다.
4️⃣ Reducer 함수는 Action 객체의 값을 확인하고, 그 값에 따라 전역 상태 저장소 Store
의 상태를 변경한다.
5️⃣ 상태가 변경되면 React는 화면을 다시 렌더링 한다.
Redux 에서는 Action → Dispatch → Reducer → Store 순서로 데이터가 단방향으로 흐른다.
Store 는 상태가 관리되는 오직 하나뿐인 저장소 역할을 한다. Redux 앱의 state가 저장되어 있는 공간
import { createStore } from 'redux';
const store = createStore(rootReducer);
import { Provider } from "react-redux";
⇒ react-redux에서 Provider를 불러와야한다. (Provider는 store를 손쉽게 사용할 수 있게 하는 컴포넌트)
⇒ 불러온 후 Store를 사용할 컴포넌트를 감싸준 후 Provider 컴포넌트의 props로 store를 설정해주면 된다. <Provider store={store}>
import { legacy_createStore as createStore } from 'redux';
⇒ redux에서 createStore 불러오기
전역 상태 저장소 store를 사용하기 위해서는 App 컴포넌트를 Provider로 감싸준 후 props로 변수 store를 전달해주어야 한다.
⇒ Provider 로 감싸진 컴포넌트는 같은 state를 사용할 수 있다.
⇒ <Provider store={store}>
⇒ 하위 컴포넌트들이 props 없이 state 사용할 수 있음
변수 store에 createStore 메서드를 통해 store를 만들어 준다.
그리고 createStore에 인자로 Reducer 함수를 전달해주어야 한다.
⇒ useState 대신 createStore 사용
Reducer 는 Dispatch 에게서 전달받은 Action 객체의 type 값에 따라 상태를 변경시키는 함수 이다.
이때 Reducer 는 순수함수 여야 한다.
⇒ 외부 요인으로 인해 기대한 값이 아닌 엉뚱한 값으로 상태가 변경되는 일이 없어야 하기 때문
만약 여러개의 Reducer를 사용하는 경우 Redux의 combineReducers
메서드를 사용해 하나의 Reducer로 합쳐줄 수 있다.
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
counterReducer,
anyReducer,
...
});
Action은 말그대로 어떤 액션을 취할 것인지 정의해 놓은 객체
type
은 필수로 지정 해 주어야 한다. (대문자와 Snake Case로 작성)
⇒ 해당 Action 객체가 어떤 동작을 하는지 명시해주는 역할을 하기 때문
필요에 따라 payload
를 작성해 구체적인 값을 전달
//payload가 필요 없는 경우
{type: "INCREASE"}
//payload가 필요한 경우
{type: "SET_NUMBER", payload: 5}
보통 Action을 직접 작성하기보다는 Action 객체를 생성하는 함수를 만들어 사용하는 경우가 많다.
⇒ 이런 함수를 액션 생성자(Action Creator)
라고도 함
Dispatch는 Reducer로 Action을 전달해주는 함수 이며,
Dispatch 의 전달인자로 Action 객체가 전달
된다.
// Action 객체를 직접 작성하는 경우
dispatch( { type: 'INCREASE' } )
dispatch( { type: 'SET_NUMVER', payload: 5 } )
// 액션 생성자(Action Creator)를 사용하는 경우
dispatch( increase() );
dispatch( setNumber(5) );
⇒ Action 객체를 전달받은 Dispatch 함수는 Reducer를 호출한다.
위의 개념들을 연결해줄 때 사용한다.
React-Redux에서 Redux를 사용할 때 활용할 수 있는 Hooks 메서드를 제공하는데,
그 중 useSelector()
, useDispatch()
두가지 메서드를 기억하면 된다.
Action 객체를 Reducer로 전달해주는 Dispatch 함수를 반환하는 메서드
import { useDispatch } from 'react-redux'
const dispatch = useDispatch()
dispatch( increase() )
console.log(counter) // 2
dispatch( setNumber(5) )
console.log(counter) // 5
컴포넌트와 state를 연결하여 Redux의 state에 접근할 수 있게 해주는 메서드
import { useSelector } from 'react-redux'
const counter = useSelector(state => state)
console.log(counter) // 1
1️⃣ Single source of truth
동일한 데이터는 항상 같은 곳에서 가지고 와야 한다!
⇒ Redux에는 데이터를 저장하는 Store 라는 단 하나뿐인 공간이 있음과 연결되는 원칙
2️⃣ State is read-only
상태는 읽기 전용이라는 뜻!!!
React에서 상태생산함수로만 상태를 변경할 수 있었던 것 처럼, Redux의 상태도 직접 변경할 수 없다.
⇒ State Mutation X!! (Mutation 이란 원 객체의 참조값을 건드리면 안됨)
⇒ Action 객체가 있어야만 상태를 변경할 수 있음과 연결되는 원칙
3️⃣ Changes are made wite pure functions
변경은 순수함수로만 가능하다!!!
상태가 엉뚱한 값으로 변경되는 일이 없도록 순수함수로 작성되어야 하는 Reducer와 연결되는 원칙
⇒ 상태를 유추할 수 있어야 한다.
⇒ 상태가 tracking이 가능 해야 된다.
Store
: 상태가 관리되는 오직 하나뿐인 저장소 역할을 한다.
⇒ Redux로 state 저장하고 사용하는 방법 1
Action
: state를 어떻게 변경할지 정의 해놓은 객체
⇒ action을 기반으로 상태를 변경하는 정보를 담고 있움?
⇒ action must be plain object // 순수한 객체
⇒ Redux로 state 저장하고 사용하는 방법 2
Reducer
: 새로운 state를 만드는 순수함수 (=data modifier)
⇒ storage 안에서 관리해주는 녀석?
⇒ state(data)를 변경시키는 함수
⇒ 두개의 인자를 받음(state, action)
⇒ Redux로 state 데이터 수정하기 1
Dispatch
: Reducer로 Action을 전달해주는 함수
⇒ dispatch는 action을 reducer(상태를 바꿔주는 녀석)에게 전달해주는 녀석
⇒ reducer는 dispatch 함수로 인해서 action을 전달받음
⇒ action에 담긴 정보를 기반으로 상태를 변경 가능함
⇒ dispatch 에는 action을 담아라
⇒ 결국 state를 바꿔주는 녀석, 어떤 정보를 기반으로? Action!!
⇒ usage => dispatch({type:'ADD', payload=})
⇒ dispatch(action)
⇒ Redux로 state 데이터 수정하기 2
useDispatch
: Action 객체를 Reducer로 전달해주는 메서드
useSelector
: 컴포넌트와 state를 연결해 Store에 저장된 state에 접근할 수 있게 해주는 메서드
Redux 에서는 Action → Dispatch → Reducer → Store 순서로 데이터가 단방향으로 흐른다!!!