학습목표
useState 를 통해서 만들었던 count 프로그램을 리덕스를 사용해 다시 만들 수 있습니다.
리덕스 설정
리덕스 설치
리액트에서 리덕스를 사용하기 위해서는 2개의 패키지를 설치해야 합니다. VScode 터미널에서 아래 명령어를 입력해서 2개의 패키지를 설치합니다. 참고로 react-redux 라는 패키지는 리덕스를 리액트에서 사용할 수 있도록 서로 연결시켜주는 패키지입니다.
yarn add redux react-redux
===
# 아래와 같은 의미
yarn add redux
yarn add react-redux
폴더 구조 생성하기
좌측의 의미지와 같이 폴더 구조를 생성합니다.
- src 폴더 안에 redux 폴더를 생성
- redux 폴더 안에 config, modules 폴더 생성
- config 폴더 안에 configStore.js 파일 생성
각각의 폴더와 파일의 역할은 다음과 같습니다.
- redux : 리덕스와 관련된 코드를 모두 모아 놓은 폴더입니다.
- config : 리덕스 설정과 관련된 파일들을 놓을 폴더입니다.
- configStore : "중앙 state 관리소" 인 Store 를 만드는 설정 코드들이 있는 파일입니다.
- modules : 우리가 만들 State 들의 그룹이라고 생각하면 됩니다. 예를 들어 todo-list 를 만든다고 한다면, todo-list 에 필요한 state 들이 모두 모여있을 todos.js 를 생성하게 될텐데요, 이 todos.js 파일이 곧 하나의 모듈이 됩니다.
설정 코드 작성
설정 코드 작성 시, 주의사항
1. 작성하는 설정코드는 이해할 필요가 없는 코드들입니다. 설정 코드를 작성하는 이유는 리덕스를 만든 리덕스팀에서 이렇게 설정을 하라고 안내하고 있기 때문입니다.
2. 리덕스 사용 "방법" 을 중점으로 공부합니다.
src/configStore.js
src/configStore.js 에 아래 코드를 입력하세요.
import { createStore } from "redux"; ①
import { combineReducers } from "redux"; ②
const rootReducer = combineReducers({});
const store = createStore(rootReducer);
export default store;
① createStore()
리덕스의 가장 핵심이 되는 스토어를 만드는 메소드(함수) 입니다.
리덕스는 단일 스토어로 모든 상태 트리를 관리한다고 설명해 드렸죠?
리덕스를 사용할 시 creatorStore를 호출할 일은 한 번밖에 없을 거예요.
② combineReducers()
리덕스는 action —> dispatch —> reducer 순으로 동작한다고 말씀드렸죠?
이때 애플리케이션이 복잡해지게 되면 reducer 부분을 여러 개로 나눠야 하는 경우가 발생합니다.
combineReducers은 여러 개의 독립적인 reducer의 반환 값을 하나의 상태 객체로 만들어줍니다.
index.js
디렉토리의 가장 최상단에 있는 index.js 에 아래 내용을 입력합니다.
// 원래부터 있던 코드
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
// 우리가 추가할 코드
import store from "./redux/config/configStore";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
App을 Provider로 감싸주고, configStore에서 export default 한 store를 넣어줍니다.
모듈 만들기
모듈이란, State 의 그룹이라고 했습니다. 우리의 첫 모듈은 카운터 프로그램에 필요한 State 들이 모여있는 모듈이 될 것입니다. 아래 순서대로 파일을 생성하고, 코드를 입력해보겠습니다.
- modules 폴더에 counter.js 파일을 생성합니다.
- 아래 코드를 작성합니다.
// src/modules/counter.js
// 초기 상태값
const initialState = {
number: 0,
};
// 리듀서
const counter = (state = initialState, action) => {
switch (action.type) {
default:
return state;
}
};
// 모듈파일에서는 리듀서를 export default 한다.
export default counter;
initialState === 초기 상태값
initialState 는 단어 그대로 초기 상태값입니다. 즉, 어떤 State의 초기값을 정해주는 것입니다. useState 를 사용했을 때 괄호 안에 초기값을 지정해주던 것과 같은 이치입니다.
const [number, setNumber] = useState(0)
위 코드에서 만든 State 의 초기값은 { }(객체) 이고, 그 안에 number 라는 변수에 초기값 0 을 할당해준 것입니다. 초기값은 꼭 객체가 아니어도 됩니다. 배열이 되어도 되고, 그냥 원시데이터가 돼도 됩니다. 그리고 객체에도 여러 개의 변수를 넣어줄 수 있습니다.
// 초기값이 0 const initialState = 0; // 초기값이 0이 있는 배열 const initialState = [0]; // 초기값이 number = 0, name = '석구'인 객체 const initialState = { number: 0, name: '석구' };
Reducer === 변화를 일으키는 함수
아래 코드를 "리듀서" 라고 합니다. 리듀서란, 변화를 일으키는 함수입니다.// 리듀서 const counter = (state = initialState, action) => { switch (action.type) { default: return state; } };
useState() 를 사용했을 때, number 라는 값을 바꾸고 싶으면 setNumber 를 사용했습니다.
// 예시 코드 const onClickHandler = () => { setNumber(number + 1); // setState를 이용해서 state 변경 }
리덕스에서는 리듀서가 이 역할을 합니다. 만약 "리듀서야 number 에 +1을 해줘" 라고 명령하면, 리듀서는 number 에 +1 을 실행합니다. 그래서 변화를 일으키는 함수라고 표현한 것입니다.// src/redux/modules/counter.js // counter 리듀서 const counter = (state = initialState, action) => { switch (action.type) { default: return state; } }; export default counter; // 여기
카운터 모듈을 스토어에 연결하기
그리고 리듀서의 인자에 보면, (state = initialState, action) 이라고 되어 있습니다.
리듀서 인자 첫 번째 자리에서는 state 를, 두 번째 자리에서는 action 이라는 것을 꺼내서 사용할 수 있습니다.
여기서는 state = initialState 처럼 state 에 initialState 를 할당해줘야 하는 것만 기억하면 됩니다.
지금까지 모듈파일에서 초기 상태값과 리듀서를 작성했습니다. 이제 모듈을 스토어에 연결시켜야 합니다. 아직까진 모듈과 스토어가 각각 따로 분리되어 있는 상태이기 때문에 만들어 둔 State 를 스토어에서 꺼낼 수 없습니다.
configStore.js 로 이동해서 아래 코드를 추가합니다.
// src/redux/modules/config/configStore.js // 원래 있던 코드 import { createStore } from "redux"; import { combineReducers } from "redux"; // 새롭게 추가한 부분 import counter from "../modules/counter"; const rootReducer = combineReducers({ counter: counter, // <-- 새롭게 추가한 부분 }); const store = createStore(rootReducer); export default store;
위와 같이 코드를 추가하면, 스토어와 모듈이 연결됩니다. 이렇게 스토어와 모듈을 연결시키는 코드는 모듈을 추가할 때마다 똑같이 진행해주면 됩니다.
useSelector : 스토어 조회
useSelector 사용방법
생성한 모듈을 스토어에 잘 연결했는지 확인하는 방법은 컴포넌트에서 스토어를 직접 조회하면 됩니다. 컴포넌트에서 리덕스 스토어를 조회하고자 할 때는 useSelector 라는 'react-redux' 의 훅을 사용해야 합니다.
useSelector 의 사용방법은 아래와 같습니다.
// 1. store에서 꺼낸 값을 할당 할 변수를 선언합니다.
const number =
// 2. useSelector()를 변수에 할당해줍니다.
const number = useSelector()
// 3. useSelector의 인자에 화살표 함수를 넣어줍니다.
const number = useSelector( ()=>{} )
// 4. 화살표 함수의 인자에서 값을 꺼내 return 합니다.
// 우리가 useSelector를 처음 사용해보는 것이니, state가 어떤 것인지 콘솔로 확인해볼까요?
const number = useSelector((state) => {
console.log(state)
return state
});
App.js 컴포넌트로 이동해서 기존에 있던 코드를 모두 지우고, 아래 코드를 입력해주세요.
// src/App.js
import React from "react";
import { useSelector } from "react-redux"; // import 해주세요.
const App = () => {
const counterStore = useSelector((state) => state); // 추가해주세요.
console.log(counterStore); // 스토어를 조회해볼까요?
return <div></div>;
}
export default App;
컴포넌트에서 스토어를 조회할 때, react-redux 에서 제공하는 useSelector 라는 훅을 사용합니다.
브라우저를 켜고, 콘솔을 보면 객체가 보이고, 그 안에 counter 라는 값이 있는 것을 볼 수 있습니다. 직접 만든 counter 라는 모듈의 state 가 보이는 것을 알 수 있습니다. 이렇게 화살표 함수에서 꺼낸 state 라는 인자는 현재 프로젝트에 존재하는 모든 리덕스 모듈의 state 인 것입니다.
이제 어떤 컴포넌트에서도 접근할 수 있는 스토어를 갖게 되었습니다. 만약 우리가 컴포넌트에서 number 라는 값을 사용하고자 한다면, 아래 코드처럼 꺼내서 사용하면 됩니다.
const number = useSelector(state => state.counter.number); // 0
'항해 16기 > Today I Learned' 카테고리의 다른 글
[항해 24일차] TIL_React 숙련주차 : Redux - Payload 및 Ducks 패턴 (0) | 2023.08.30 |
---|---|
[항해 20일차] TIL_React 숙련주차 : 카운터 프로그램 만들기2 (0) | 2023.08.30 |
[항해 18일차] TIL_React 숙련주차 : Redux 란? (0) | 2023.08.30 |
[항해 17일차] TIL_React 숙련주차 : Redux 설정 (0) | 2023.08.30 |
[항해 16일차] TIL_React 숙련주차 : Styled Components (0) | 2023.08.29 |