React Redux

Goofi·2023년 3월 6일
0
post-custom-banner

React Redux

❗️해당 게시물은 Veloperty Redux를 학습하고 정리한 게시물 입니다.

Redux 와 Context API 차이

1.미들웨어 존재 유무

  • 리덕스에는 미들웨어라는 개념 존재
  • 리덕스의 미들웨어를 사용하면 액션 객체가 리듀서에서 처리되기 전에 우리가 원하는 작업들을 수행 가능

2.유용한 함수 & Hooks

  • Context API와 useReducer를 사용 할 때에는 여러가지 설정이 필요하다.
  • Redux 에서는 connect함수를 이용하여 리덕스의 상태 또는 액션 생성 함수를 컴포넌트의 props로 받아 올수 있다.
  • Redux 에서는 useSelector, useDispatch,useStore 같은 Hooks를 사용하면 손쉽게 상태를 조회 또는 액션 디스패치 할 수 있다.

3. 하나의 커다란 상태

리덕스에서는 모든 글로벌 상태를 하나의 커다란 상태 객체에 넣어서 사용하는 것이 필수이다.

❗️단순히 글로벌 상태 관리를 위한 것이라면 Context API를 활용하는 것 만으로 충분하다.

결론

리덕스 언제 써야 할까?
1. 프로젝트의 규모가 크면 Redux 아니면 Context API
2. 비동기 작업을 자주하면 Redux 아니면 Context API
3. 리덕스를 배워보니까 사용하는게 편하면 Redux 아니면 Context API

🔑 Redux 키워드

액션 (Action)

상태에 변화가 필요할 때 발생시킴 (객체하나로 표현)
type을 필수로 그외의 값들은 개발자 마음대로 생성

액션 생성함수 (Action Creator)

컴포넌트에서 더욱 쉽게 액션을 발생시키기 위함
필수 아님

리듀서 (Reducer)

변화를 일으키는 함수
현재의 상태와 액션을 참조하여 새로운 상태를 반환
리듀서에서는 불변성을 꼭 지켜줘야한다.

아래 코드도 원래는 state를 복사해야 된다.

function counter(state, action){
	switch(action.type){
      case 'INCREASE':
        return state + 1;
      case 'DECREASE':
        return state - 1;
      default:
        return state;
    }
}

useReducer에선 일반적으로 default: 부분에 throw new Error('Unhandled Action')과 같은 에러를 발생시킨다. 하지만 Redux 리듀서에서는 기존 state를 그대로 반환한다.

스토어 (Store)

한 애플리케이션당 하나의 스토어
현재의 앱 상태와, 리듀서, 내장함수 포함

디스패치 (dispatch)

스토어의 내장함수
액션을 발생 시키는 것

리덕스에서 불변성을 유지해야 하는 이유
shallow equality 검가 때문이다.

구독(subscribe)

스토어 내장함수
subscribe 함수에 특정 함수를 전달해주면, 액션이 디스패치 되었을 때마다 전달해준 함수가 호출
→ 리액트에서는 connect 함수 또는 useSelector Hook을 사용

⭐️ 리덕스의 3가지 규칙

하나의 애플리케이션 안에는 하나의 스토어를 가져야 한다.

  • 하나의 App에는 하나의 스토어를 만들어 사용한다.
  • 필수는 아니지만 권장하지 않는다.
  • 개발 도구를 활용할 수 없기 때문이다.

상태는 읽기 전용이다.

  • 기존의 상태를 수정하지 않고 새로운 상태를 생성하여 업데이트한다. (교체의 개념)
  • 이를 통해 불변성을 유지할 수 있다.
  1. 데이터의 변경을 감지하기 위해서는 내부 데이터까지 전부 찾아봐야 하는데 이 경우 시간이 너무 오래 걸린다. 2. 따라서 기존 상태의 객체를 새로운 객체로 변경하면 객체의 주소가 다르므로 변경을 쉽게 감지하는것이 가능하다.

리듀서는 순수한 함수여야 한다.

  • 리듀서는 이전 상태와 액션 객체를 파라미터로 받는다.
  • 이전의 상태는 건들이지 않고 변화로 새로운 상태 객체를 만든다.
  • 동일 인풋에 대한 동일 아웃풋이 보장되어야 한다. (순수해야 한다.)

❗️하지만 그렇지 않은 경우도 존재한다. 이때 리덕스 미들웨어라는 것을 사용한다.

리덕스 모듈

Ducks 패턴

리듀서와 액션 관련 코드들을 하나의 파일에 몰아서 작성하는 형태

루트 리듀서

한 프로젝트에 여러개의 리듀서를 합친 것을 루트 리듀서라고 한다.
combindeReducers라는 함수를 사용하면 된다.

combineReducers

  • 각 reducer를 호출하여 초기 상태를 검색
  • 초기 상태를 정리해서 초기 상태 트리 생성
  • reducer의 처리를 정리한 combination 함수를 리턴

counter 모듈, todos 모듈 만들었다고 가정

import { combineReducers } from 'redux';
import counter from './counter';
import todos from './todos';

const rootReducer = combineReducers({
	counter,
  	todos
})

export default rootReducer;

combineReducers 와 Redux toolkit의 configureStore 조합


import { combineReducers } from 'redux';
import { configureStore } from '@reduxjs/toolkit';
import counter from './counter';
import todos from './todos';

const rootReducer = combineReducers({
	counter,
  	todos
});

const store = configureStore({
	reducer : rootReducer
});

export default store;

참고자료

리덕스를 활용한 컴포넌트 종류

프리젠테이셔널 컴포넌트

리덕스 스토어에 직접적으로 접근하지 않고 필요한 값 또는 함수를 props 로만 받아와서 사용하는 컴포넌트이다.

  • 프리젠테이셔널 컴포넌트에선 주로 UI를 선언하는 것에 집중하며 필요한 값들이나 함수는 props로 받아와서 사용하는 형태로 구현한다.

컨테이너 컴포넌트

리덕스 스토어의 상태를 조회하거나, 액션을 디스패치 할 수 있는 컴포넌트를 의미한다. 그리고, HTML 태그들을 사용하지 않고 다른 프리젠테이셔널 컴포넌트들을 불러와서 사용

Veloperty 쌤 : 저는 개인적으로 프리젠테이셔널 / 컨테이너 컴포넌트를 구분지어서 작성하긴 하지만 디렉터리 상으로는 따로 구분 짓지 않는 것을 선호합니다.

리덕스 개발자도구

설치

yarn add @redux-devtools/extension

composeWithDevTools()작성

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import App from './App';
import './exercise'
import rootReducer from './modules';

const root = ReactDOM.createRoot(document.getElementById('root'));

const store = createStore(rootReducer, composeWithDevTools());


root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);
profile
오늘보단 내일이 강한 개발자입니다!🧑🏻‍💻
post-custom-banner

0개의 댓글