로컬에서는 특정 컴포넌트 안에서만 관리되는 상태이며,
전역에서는 프로덕트 전체 혹은 여러 컴포넌트에서 관리되는 상태를 말한다.
예전에 배웠던 state 상태는 상위 컴포넌트에서 하위 컴포넌트로 props 로 상태를 전달하면서 전역상태에서 사용될 수 있다. 서로 다른 컴포넌트가 동일한 상태를 다룬다면 두 컴포넌트의 공동적인 상위 컴포넌트, 오직 한 군데에서 가져올 수 있다. 즉, 동일한 데이터는 항상 같은 곳에서 데이터를 가지고 온다는 신뢰할 수 있는 단일 출처(Single source of truth), 이를 하나의 출처 혹은 전역 공간이라고 한다.
이렇게 해야지만 데이터의 무결성을 보장한다. 데이터 무결성이란 데이터의 정확성을 보장하기 위해 데이터의 변경이나 수정 시 제한을 두어 안정성을 저해하는 요소를 막고 데이터 상태들을 항상 옳게 유지하는 것을 말한다.
따라서 상태관리를 하므로써 Props Drilling 이슈를 해결하고 전역 상태 저장소를 제공할 수 있다.
✅ 상위 컴포넌트의 state를 하위 컴포넌트에게 전달하려면 하위 컴포넌트의 props 를 통해 전달하는 현상
이렇게 props 를 통해 전달하는 props drilling 을 방지하기 위해 state는 될 수록 가까이 유지하는 방법과 상태관리 라이브러리 (Redux, Content api, Mobox, Recoil)를 사용한다.
✅ state 상태가 관리되는 오직 하나뿐인 저장소의 역할
import { createStore } from 'redux';
const store = createStore(rootReducer);
바뀌는 상태값인 수량과 plus 함수와 minus 함수를 [Parents Component]에서 정의해 준 다음 [Child4 Component] 로 전달하기 위해 그 사이의 [Child 1,2,3 Component]를 거칠 필요없이
단지 사용되는 컴포넌트는 [Parents Component]와 [Child4 Component] 이기 때문에 두 개의 컴포넌트에서만 사용될 수 있도록 한다. state 를 변경시키고자 하는 [Child4 Component] 에서 const dispatch = useDispatch();
와 함수를 통해 reducer.js 에서 설정해놓은 type을 지정해주면, 바뀐 state 값을 사용하고자 하는 [Parents Component] 에서 const 변수 = useSelecotr((state) => state);
변수를 생성하여 쓸 수 있도록 한다.
마찬가지로 state 를 변경시켜주어야 할 [Child6 Component]와 변경시킨 state 값을 적용시켜야 할 [Child3 Component]에만 Redux 를 사용하면 된다.
① 상태가 변경되어야 하는 이벤트가 발생하면, 변경될 상태에 대한 정보가 담긴 Action 객체가 생성된다.
② Action 객체는 Dispatch 함수의 인자로 전달된다.
③ Dispatch 함수는 Action 객체를 Reducer 함수로 전달해준다. ➡️ Dispatch 함수는 Reducer 함수에게 상대 변경 신청을 하는 역할
④ Reducer 함수는 Action 객체의 값을 확인하고, 그 값에 따라 전역 상태 저장소 Store의 상태를 변경한다.
⑤ 상태가 변경되면, React는 화면을 다시 렌더링 한다.
즉, Redux에서는 Action → Dispatch → Reducer → Store 순서로 데이터가 단방향으로 흐르게 된다.
- 상태가 관리되는 하나뿐인 저장소의 역할로 state 가 저장되어 있는 공간
createStore
메서드로 Reduceer 를 연결하여 Store 생성import { createStore } from 'redux'; const store = createStore(rootReducer);
- Dispatch 에게서 전달받은 Action 객체의 type 값에 따라 상태를 변경시키는 함수
- Reducer 생성할 때 초기 상태를 인자로 요구
- Action 객체의 type 에 따라 switch 조건문으로 상태 리턴
- 순수함수로써 외부요인으로 인해 기대한 값으로만 상태가 변경되어야 함
- 여러 개의 Reducer 를 사용할 때는
combineReducers
메서드로 하나의 Reducer 로 합쳐줌const reducer = (state = ___ , action) => { switch(action.type){ case '___' : return __; case '___' : return __; default : return __; } } //여러 개의 Reducer 일 경우 import { combineReducers } from 'redux'; const rootReducer = combineReducrs({ counterReducer, anyReducer, ... });
- 어떤 액션을 취할 것인지 정의해 놓은 객체
- type 필수로 지정해주어야 그에 맞는 역할을 하는 함수로 적용시키며, Snake Case 로 작성함
- payload 옵션으로 구체적인 값을 전달함
- Action 객체를 직접 작성하기보다는 Action 객체 생성 함수(액션 생성자 Action Creator) 사용함
//payload 필요없는 경우 const increase = () => { return { type: 'INCREASE' } } //payload 필요한 경우 const setNumber = (num) => { return { type: 'SET_NUMBER', payload: num; } }
- 전달인자로 Action 객체를 Reucder에게 전달해주는 함수
- Action 객체를 전달받은 Dispatch 함수는 Reducer 호출
//Action 객체를 직접 작성하는 경우 dispatch( { type: 'INCREASE' } ); dispatch( { type: 'SET_NUMBER', payload: 5 } ); //액션 생성자 Action Creator 를 사용하는 경우 dispatch(increase()); dispatch(setNumber(5));
- Action 객체를 Reducer 로 전달해주는 Dispatch 함수 반환하는 메서드
import { useDispatch } from 'react-reducx'; const dispath = useDispatch(); dispatch(increase()); dispatch(setNumber(5));
- 컴포넌트와 state를 연결하여 Redux의 state에 접근하게 해주는 메서드
import { useSelector } from 'react-redux'; const counter = useSelector(state => state); console.log(counter);
① Single source of truth : 동일한 데이터는 출처가 항상 같은 곳 (=Store)이어야 한다.
② State is read-only : 상태는 읽기전용. React 처럼 Redux도 상태를 직접 변경할 수 없고 상태갱신함수로 상태를 간접적으로 변경시켜야 함. Action 객체가 존재해야만 상태 변경 가능.
③ Changes are made with pure functions : 변경은 순수함수 (=Reducer)로만 가능함.