위의 이미지는 리덕스를 통해서 만든 장면이다. input의 정보를 useState를 통하여 정보를 받는 것 까지는 리덕스 없이 구현했던 것과 동일하다. 그러나 나머지는 전부다르다. 새롭게 만들어가면서 해당 내용을 최대한 복습해보자.
새롭게 CRA를 통해서 새롭게 리액트를 생성하고, 리덕스를 사용하기 위해서 두개의 라이브러리를 설치관리자를 통해서 설치해주자.
yarn add redux react-redux
그러고 보니 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"
} ]
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을 통해서 이번 과제를 수행하고자 한다.
const initialState = {
number:0,
};
const counter = (state = initialState, action) => {
switch (action.type) {
default:
return state;
}
}
const counter = (state = initialState, action) => {} 리듀서 함수를 생성해 준다. 이때 ES6 문법에 따라 매개변수 초기값(Default parameter)을 위와 같이 설정해 주었다.
import counter from "../modules/counter";
const rootReducer = combineReducers({
counter,
});
모듈을 생성했다면, 중앙저장소로 이동해서 해당 모듈을 임포트 해주고, combineReducers에 추가해주어야 등록이 완료된다. 이로써 전역에서 사용할 수 있는 상태를 만든 것이다. 모듈을 생성했다면, 이렇게 등록해서 사용하면 된다.
//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>
를 생성하면 자동으로 const root 부분은 생성될 것이다. 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에 접근하게 되어 사용할 수 있게 되는 것이다.
퀴즈를 다시 돌아보며 직면한 것은 Human Error 정상적인 로직임에도 동작하지 않는 것은 사소한 오타 때문이었다. 이러한 Human Error를 극복하고자 등장한 것이 있으니, Ducks 패턴이다. 개발자 Erik Rasmussn 의 제안으로 시작된 해당 패턴은 현재 리덕스 모듈 작성방식의 정석으로 여겨지고 있다.
Ducks 패턴이란 리듀서함수를 공부하면서 보았던 onClick={} 함수 내부에 정의된 내용을 모듈에서 사전에 만들고, App.jsx에 임포트해서 사용하는 방법을 말한다.
먼저 안전하게 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