조금조금 REACT, ReDUX(실전)

Edwin·2023년 3월 4일
1

조금조금 REACT

목록 보기
17/31
post-thumbnail

조금조금 REACT, ReDUX(실전)

위의 이미지는 리덕스를 통해서 만든 장면이다. input의 정보를 useState를 통하여 정보를 받는 것 까지는 리덕스 없이 구현했던 것과 동일하다. 그러나 나머지는 전부다르다. 새롭게 만들어가면서 해당 내용을 최대한 복습해보자.

1) 첫번째 할 일은 리덕스를 설치하는 일이다.

새롭게 CRA를 통해서 새롭게 리액트를 생성하고, 리덕스를 사용하기 위해서 두개의 라이브러리를 설치관리자를 통해서 설치해주자.

yarn add redux react-redux

2) 리덕스 환경설정 해주기, 폴더를 생성하는 일

  • src > redux 폴더
  • redux > config, modules 폴더
  • config > configStore.js

그러고 보니 vscode 단축키 없나? 하고 찾아봤더니 JSON에 단축키 역시도 수동으로 설정해주어야 하더라.

먼저, 맥OS 기준 Command+p 를 눌러서 검색창을 열고
둘째, >open keyboard Shortcuts(JSON) 을 찾아서 들어간다.
셋째, 아래와 같이 객체로 정보를 넣어주면 된다. 일단 나는 간단하게 아래와 같이 설정했다.

// 키 바인딩을 이 파일에 넣어서 기본값 재정의, 그러면 최초의 상태를 볼 수 있을 것이다. 
// 해당부분을 객체로 추가해주면 된다. 

[] 

    [ {
        "key": "cmd+n",
        "command": "explorer.newFile",
        "when": "explorerViewletFocus"
      },
      {
        "key": "cmd+f",
        "command": "explorer.newFolder",
        "when": "explorerViewletFocus"
      } ]

3) 중앙저장소생성하기(createStore), 모듈통합(combineReducers)

import { legacy_createStore as createStore } from "redux";
import { combineReducers } from "redux";

리덕스 4.2 이전에서는 중앙저장소 생성에 대한 임포트로 import { createStore } from "redux"가 사용되었다. 그런데 취소선이 생겨났다. 현재까지 해당 임포트는 사용에 있어서 문제가 되지 않지만, 리액트 팀에서 권장하지 않기 때문에 취소선으로 개발자에게 알려주는 것이라고 한다.

일단 취소선 자체를 없애고 싶다면 legacy_createStore를 설치하고 이름을 변경해주어, 본문에서 사용하면 된다. 그러나 리액트 팀에서 권장하는 바는 @reduxjs/toolkit 설치하여 이를 활용하는 것이다. 이를 위해서는 설치관리자를 통해서 터미널에서 라이브러리를 설치해야 한다.

yarn add @reduxjs/toolkit -D

그리고 임포트 해주면 사용이 가능해 진다.

import { configureStore } from '@reduxjs/toolkit'

그러나 아직 해당 방법의 사용법을 숙지 하지 않았기 때문에, 권장되지는 않지만 4.2 버전 이하에서 사용되었던 createStore을 통해서 이번 과제를 수행하고자 한다.

3) 리듀서 모듈 생성하기

  • modules 폴더로 이동해서 모듈을 생성한다.
const initialState = {
  number:0,
};

const counter = (state = initialState, action) => {
  switch (action.type) {
    default:
      return state;
  }
}

const counter = (state = initialState, action) => {} 리듀서 함수를 생성해 준다. 이때 ES6 문법에 따라 매개변수 초기값(Default parameter)을 위와 같이 설정해 주었다.

4) 중앙저장소 모듈통합(combineReducers)에 추가

import counter from "../modules/counter";

const rootReducer = combineReducers({
  counter, 
});

모듈을 생성했다면, 중앙저장소로 이동해서 해당 모듈을 임포트 해주고, combineReducers에 추가해주어야 등록이 완료된다. 이로써 전역에서 사용할 수 있는 상태를 만든 것이다. 모듈을 생성했다면, 이렇게 등록해서 사용하면 된다.

5) App.js에서 저장된 state 사용하기

먼저 index.js에서 설정해줄 부분이 있다. Provider 생성하기

//index.js
import { Provider } from 'react-redux';
import store from './config/configStore'

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

root.render(
  <Provider store={store}>
    <App />
  </Provider>
);
  • Provider : 저장소를 하위컴포넌트에 공유해 줄 Provider를 사용하기 위해 임포트
  • store : 저장소의 내용을 전달해 주기 위해서 임포트 및, Provider에 속성주기
  • <Provider> 를 생성하면 자동으로 const root 부분은 생성될 것이다.

이제 App.js로 가자.

import { useSelector } from 'react-redux';

function App() {
  const counter = useSelector((state)=> {
    return state.counter
  });

  return (
    <>
    <p>리덕스 상태관리저장소 사용하기</p>
    <p>count 모듈의 초기값 불러오기 {counter.number}</p>
    </>
  )
}

export default App;

index.js에서 Provider를 선언했지만, 해당 컴포넌트에서 저장소의 값을 사용하기 위해서는 useSelector를 통해서 해당 저장소에서 가져올 값을 선언해주어야 한다.

  const counter = useSelector((state)=> {
    return state.counter
  });

위의 명령을 통해서 configStore.js에 있는

const rootReducer = combineReducers({
  counter
});

rootReducer의 counter를 불러와서 사용한다는 의미이다. 여기서 state는 별도로 지정한 적은 없지만, rootReducer 내에 있는 {객체}에 대한 식별자(객체명)에 해당된다. 즉, counter를 사용하기 위해서는 state.counter를 통해서 접근해야 하는 것이다.

 <p>count 모듈의 초기값 불러오기 {counter.number}</p>

그리고 state.counter의 값은 counter.jsx에서 전언된 state 객체의 key를 통해서 해당 프로퍼티의 value에 접근하게 되어 사용할 수 있게 되는 것이다.

6) Module(counter)의 상태 변경하기

퀴즈를 다시 돌아보며 직면한 것은 Human Error 정상적인 로직임에도 동작하지 않는 것은 사소한 오타 때문이었다. 이러한 Human Error를 극복하고자 등장한 것이 있으니, Ducks 패턴이다. 개발자 Erik Rasmussn 의 제안으로 시작된 해당 패턴은 현재 리덕스 모듈 작성방식의 정석으로 여겨지고 있다.

Ducks 패턴이란 리듀서함수를 공부하면서 보았던 onClick={} 함수 내부에 정의된 내용을 모듈에서 사전에 만들고, App.jsx에 임포트해서 사용하는 방법을 말한다.

  • 한 개의 모듈 파일은 아래의 것을 모두 포함해야 한다.
    1. Action type : switch 문의 case
    2. Action Creator : dispatch 내부의 내용들
    3. reducer 함수

Modules 설정하기 : Action type, Action Creator

먼저 안전하게 Action type을 설정하는 것은 변수를 활용하는 것이다.

// Modules > counter.jsx
// Action Value(type 설정)
const PLUS_INPUT = "plusNumberInput";

// Action Creator
export const plusNumber = (payload) => {
  return {
    type: PLUS_INPUT,
    payload,
  }
};

// Initial State
const initialState = {
  number:0,
};

// Reducer
const counter = (state = initialState, action) => {
  switch (action.type) {
    case PLUS_INPUT : 
      return {
        number : state.number + action.payload
      }  
   	default:
      return state;  
   }
};

// export default reducer
export default counter;

이렇게 하면 모듈이 완성된 것이다. 이를 컴포넌트에서 사용하면 되는데 방법은 아래와 같다.

컴포넌트 설정하기

// 모듈에서 내보낸 Action Creator를 사용하기 위해 임포트 해준다. 
import { plusNumber } from './modules/counter';
// 또한 dispatch 를 이요하기 위해서 임포트 해준다. 
import { useDispatch } from 'react-redux';
// input의 값을 받아오기 위한 useState()
import React, { useState } from 'react'

function App() {
  ...
  const dispatch = useDispatch();
  const [payload, setPayload] = useState(0)
  ...
  return (
  	...
    <input step="1" type="number" value={payload} onChange={(e) => setPayload(Number(e.target.value))}/>
    <button onClick={()=> dispatch(plusNumber(payload))}>input 값으로 state 변경하기</button>
    ...
  )

export default App;

모듈에서 설정한 Action Creator의 매개변수로 App.jsx에서 설정한 payload(useState)가 인자로 담겨져며 dispatch로 인해서 모듈 counter로 전달된다. 모듈 counter에서는 해당 action.type에 따라서 state를 변경하고, 중앙저장소에서 처리된 이 과정이 redux 체계 내에 있는 모든 선언에서 적용되는 것이다.

Author. EDWIN
date. 23/03/05

profile
신학전공자의 개발자 도전기!!

0개의 댓글