React 상태관리, Redux

jeongjwon·2023년 4월 24일
0

SEB FE

목록 보기
41/56

상태관리

로컬에서는 특정 컴포넌트 안에서만 관리되는 상태이며,
전역에서는 프로덕트 전체 혹은 여러 컴포넌트에서 관리되는 상태를 말한다.

예전에 배웠던 state 상태는 상위 컴포넌트에서 하위 컴포넌트로 props 로 상태를 전달하면서 전역상태에서 사용될 수 있다. 서로 다른 컴포넌트가 동일한 상태를 다룬다면 두 컴포넌트의 공동적인 상위 컴포넌트, 오직 한 군데에서 가져올 수 있다. 즉, 동일한 데이터는 항상 같은 곳에서 데이터를 가지고 온다는 신뢰할 수 있는 단일 출처(Single source of truth), 이를 하나의 출처 혹은 전역 공간이라고 한다.

이렇게 해야지만 데이터의 무결성을 보장한다. 데이터 무결성이란 데이터의 정확성을 보장하기 위해 데이터의 변경이나 수정 시 제한을 두어 안정성을 저해하는 요소를 막고 데이터 상태들을 항상 옳게 유지하는 것을 말한다.

따라서 상태관리를 하므로써 Props Drilling 이슈를 해결하고 전역 상태 저장소를 제공할 수 있다.



Props Drilling

✅ 상위 컴포넌트의 state를 하위 컴포넌트에게 전달하려면 하위 컴포넌트의 props 를 통해 전달하는 현상

  • props 의 전달횟수가 많아진다면 코드의 가독성이 나빠지고, 코드의 유지보수(어느 컴포넌트에서 에러가 발생했는지)도 힘들어진다.
  • state 변경시 props 전달 과정에서 불필요하게 관여한 컴포넌트 또한 리렌더링이 발생하게 되어 악영향을 미친다.

이렇게 props 를 통해 전달하는 props drilling 을 방지하기 위해 state는 될 수록 가까이 유지하는 방법과 상태관리 라이브러리 (Redux, Content api, Mobox, Recoil)를 사용한다.



전역 상태 저장소

✅ state 상태가 관리되는 오직 하나뿐인 저장소의 역할

  • createStore 메서드를 활용해 Reducer를 연결해서 Store를 생성한다.
	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 를 사용하면 된다.





Redux

① 상태가 변경되어야 하는 이벤트가 발생하면, 변경될 상태에 대한 정보가 담긴 Action 객체가 생성된다.
② Action 객체는 Dispatch 함수의 인자로 전달된다.
③ Dispatch 함수는 Action 객체를 Reducer 함수로 전달해준다. ➡️ Dispatch 함수는 Reducer 함수에게 상대 변경 신청을 하는 역할
④ Reducer 함수는 Action 객체의 값을 확인하고, 그 값에 따라 전역 상태 저장소 Store의 상태를 변경한다.
⑤ 상태가 변경되면, React는 화면을 다시 렌더링 한다.
즉, Redux에서는 Action → Dispatch → Reducer → Store 순서로 데이터가 단방향으로 흐르게 된다.


Store

  • 상태가 관리되는 하나뿐인 저장소의 역할로 state 가 저장되어 있는 공간
  • createStore 메서드로 Reduceer 를 연결하여 Store 생성
import { createStore } from 'redux';
const store = createStore(rootReducer);

Reducer

  • 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,
    ...
});

Action

  • 어떤 액션을 취할 것인지 정의해 놓은 객체
  • type 필수로 지정해주어야 그에 맞는 역할을 하는 함수로 적용시키며, Snake Case 로 작성함
  • payload 옵션으로 구체적인 값을 전달함
  • Action 객체를 직접 작성하기보다는 Action 객체 생성 함수(액션 생성자 Action Creator) 사용함
//payload 필요없는 경우
const increase = () => {
	return {
    	type: 'INCREASE'
    }
}
//payload 필요한 경우
const setNumber = (num) => { 
	return {
    	type: 'SET_NUMBER',
        payload: num;
    }
}

Dispatch

  • 전달인자로 Action 객체를 Reucder에게 전달해주는 함수
  • Action 객체를 전달받은 Dispatch 함수는 Reducer 호출
//Action 객체를 직접 작성하는 경우
dispatch( { type: 'INCREASE' } );
dispatch( { type: 'SET_NUMBER', payload: 5 } );
//액션 생성자 Action Creator 를 사용하는 경우
dispatch(increase());
dispatch(setNumber(5));



Redux Hooks

useDispatch()

  • Action 객체를 Reducer 로 전달해주는 Dispatch 함수 반환하는 메서드
import { useDispatch } from 'react-reducx';
const dispath = useDispatch();
dispatch(increase());
dispatch(setNumber(5));

useSelector()

  • 컴포넌트와 state를 연결하여 Redux의 state에 접근하게 해주는 메서드
import { useSelector } from 'react-redux';
const counter = useSelector(state => state);
console.log(counter);

⭐️ Redux 3원칙

① Single source of truth : 동일한 데이터는 출처가 항상 같은 곳 (=Store)이어야 한다.
② State is read-only : 상태는 읽기전용. React 처럼 Redux도 상태를 직접 변경할 수 없고 상태갱신함수로 상태를 간접적으로 변경시켜야 함. Action 객체가 존재해야만 상태 변경 가능.
③ Changes are made with pure functions : 변경은 순수함수 (=Reducer)로만 가능함.



0개의 댓글