리덕스 개념 이해

히치키치·2021년 11월 15일
0

React_Advance

목록 보기
1/9
post-thumbnail

소개

  • App에서 모든 상태의 로직 관리
  • 컴포넌트 state 업데이트하면 App 컴포넌트 re-rendering됨
  • 상위 컴포넌트 re-rendering하면 하위 컴포넌트도 re-rendering됨
  • 여러개의 컴포넌트 거쳐 props 전달해야함

리덕스 : 상태 관리의 로직을 컴포넌트 외부에서 처리

스토어 :

어플리케이션 상태 값 내장
상태 변화 필요시 액션이 전달되는 곳

액션 :

상태 변화 일으킬 때 참조하는 객체
상태 변화 요구 스토어에 전달됨

디스패치 :

액션을 스토어에 전달

리듀서 :

상태 변화시키는 로직 존재 함수
스토어 액션 전달 받으면 상태 변경법 정하고, 액션 처리 후 새 상태 스토어에 저장

구독 :

스토어 값이 필요한 컴포넌트는 스토어 구독함
스토어 안 상태가 변경되면 스토어를 구독하는 컴포넌트에 바로 전달

리덕스 사용

1. JSBin 준비

리덕스 파일 불러오기

2. 액션과 액션 생성 함수

액션

  • 스토어에서 상태 변화 일으킬 때 참조하는 객체
  • 반드시 type 값 명시 -> 고정적 & 어떤 작업하는지 정의
  • 구체적인 작업 방식은 리듀서에서 정의

액션 생성 형식

{
  type : "INSERT_TODO",
  text : "리액트 공부"
}
  1. 객체 형태 넣기
{
  type : "INSERT_TODO",
  todo : {
  	id :1,
     	text:"리액트 배우기",
        done : false
  }
}

액션 생성 함수

  • 액션 새롭게 생성 시 직접 객체를 만드는 경우 액션 형식 모두 외워야하는 번거로움 발생
  • 액션 타입 상수 값으로 정의하고 액션 생성 함수 이용해 액션 생성
  • 고정적인 액션 타입 외 유동적인 값 들어가야 하면 파라미터 이용해 액션 생성
const INCREMENT="INCREMENT";
const DECREMENT ="DECREMENT";

const increment=(diff)=>({
  type : INCREMENT,
  diff:diff
});

const decrement=(diff)=>({
  type :DECREMENT,
  diff:diff
});



console.log(increment(1));
console.log(decrement(1));

액션 객체 기록 결과 :

3. 리듀서 : 변화를 일으키는 함수

파라미터

  • 1st : 현재 상태
  • 2nd : 액션 객체

함수 내부

  • switch문 사용해 action.type에 따라 새로운 상태 만들어 반환

리듀서 생성

  • 리듀서 초기에 사용할 초기 상태 initialState 정의 필요함

예시 [1] : 새 객체 생성해 그 안 number 키의 값을 0으로 설정하는 코드

  • state=initialState :
    state 값이 undefined인 경우 initialState을 기본값으로 사용
  • 함수 내부 action.type 따른 switch문:
    현재 상태와 액션 객체 참조해 새 객체 생성
//1. initialState 정의
const initialState={
	number : 0
}

//2. 리듀서 함수 counter : 숫자 빼고 더하는 기능
function counter(state=initialState,action){
	switch(action,type){
    	case INCREMENT:
        	return {number : state.number + action.diff};
        case DECREMENT:
        	return {number : state.number - action.diff};
        default:
        	return state;
    }
}

예시 [2] : state의 값이 여러 개인 경우

  • 상태 업데이트 : 새로운 객체 만들고 그 안에서 상태 정의
  • Object.assign 실행 : 파라미터로 전달된 객체 순서대로 합쳐줌
const initialState={
  number :1,
  foo:"bar",
  baz:"qux"
}

function counter(state=initialState,action){
	switch(action.type){
      case INCREMENT:
        return Object.assign({},state,{
        	number :state.number+action.diff
        });
      case DECREMENT:
        return Object.assign({},state,{
          	number :state.number -action.diff
        });
       default:
  		return state;
    };
}

전체 소스 코드


const INCREMENT="increment";
const DECREMENT="decrement";

const increment = (diff)=>({

  type : INCREMENT,
  diff : diff
});

const decrement=(diff)=>({
  
    type : DECREMENT,
    diff:diff
});


const initialState={
  number :1,
  foo:"bar",
  baz:"qux"
};

function counter(state=initialState,action){
	switch(action.type){
      case INCREMENT:
        return Object.assign({},state,{
        	number :state.number+action.diff
        });
      case DECREMENT:
        return Object.assign({},state,{
          	number :state.number -action.diff
        });
       default:
  		return state;
    };
};

console.log(counter(undefined,increment(1)));
console.log(counter(undefined,decrement(1)));
//원칙적으로는 리덕스 사용하기 때문에 이렇게 직접 리듀서 함수 실행하는 일 없음

액션 객체 기록 결과 :

4. 리덕스 스토어 생성

  • 액션과 리듀서 준비 완료시 생성 가능

스토어 생성 함수

  • 첫 파라미터 : 리듀서 함수
  • 두번째 파라미터 : 해당 값을 스토어 기본 값으로 사용
    (생략시 리듀서 초기값 이용)
import {createStore} from "redux";
/*jsbin에서는 const {createStore}=Redux; 이거 사용*/
const store = createStore(counter);

5. 구독

  • 주로 react-redux의 connect 함수 사용함
  • 리덕스 스토어의 상태가 바뀔 때마다 특정 함수 실행함
    redux의 subscribe 함수 사용하는 경우는 드물지만 이해 위해 사용
const unsubscribe =store.subscribe(()=>{
  console.log(store.getState())
});

subscribe 함수

  • 함수 형태의 파라미터 :
    전달된 파라미터의 함수는 스토어 상태 변화 발생시 마다 호출됨
  • subscribe 함수가 호출되면 구독 취소하는 unscribe 함수 반환함

unsubscribe 함수

  • 구독 취소시 unsubscribe() 입력해 호출

getState 함수

  • 현재 스토어 상태 반환

6. dispatch로 액션 전달

  • 스토어에 액션 넣을 때 store.dispatch 사용

리덕스 3가지 규칙

1. 스토어는 단 1개

  • 스토어는 언제나 단 1개
  • 리듀서 여러개 만들어 관리 가능

2. state는 읽기 전용

  • 리덕스의 상태 state는 읽기 전용
  • 상태 업데이트 시 새 상태 객체 생성 해야 함
  • 자동 메모리 관리로 인해 Object.assign 사용시에도 메모리에 객체 누적 없음
  • nested 객체는 내부 깊은 값 복사 X, 객체 key 레퍼런스만 복사 하여 성능 악화 없음

3. 변화는 순수 함수로 구성

  • 순수 함수에서 결과 값 출력시 파라미터 값에만 의존
    (같은 파라미터 -> 같은 결과)
  • 리듀서 함수 내부에서 외부 네트워크와 데이터베이스에 직접 접근 불가
    (new Date(), Math.random 등 사용 불가능)

0개의 댓글