Redux를 사용하기 위해서는 redux와 react-redux를 설치해야한다.
설치를 하고 나면,
DEPENDENCIES
redux, react-redux가 설치되어 있는 것을 확인할 수 있다.
.
.
.
"dependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-native": ">=0.59",
"react-redux": "^8.0.2",
"redux": "^4"
},
.
.
.
index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
// (1) react-redux에서 Provider을 불러온다. (Provider은 store을 쉽게 사용할 수 있게 하는 컴포넌트)
// 해당 컴포넌트를 불러온 다음, Store을 사용할 컴포넌트를 감싼 후, Provider 컴포넌트의 props로 store을 설정해준다.
import { Provider } from 'react-redux';
// (2) redux에서 createStore을 불러온다.
import { legacy_createStore as createStore } from 'redux';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
// (6) Action은 어떻게 state를 변경할지 정의해놓은 객체로 type은 필수로 지정을 해줘야 한다
export const increase = () => {
return {
type: 'INCREASE',
};
};
export const decrease = () => {
return {
type: 'DECREASE',
};
};
const count = 1;
// (5) Reducer를 생성할 때에는 초기 상태(default value)를 첫 번째 인자, action 객체가 두 번째 인자로 들어온다.
// action 객체에서 정의한 type에 따라 새로운 state를 리턴하며, 새로운 상태는 전역 변수 저장소 store에 저장된다.
const counterReducer = (state = count, action) => {
// Action 객체의 type 값에 따라 분기하는 switch 조건문
switch (action.type) {
case 'INCREASE': //action === 'INCREASE'일 경우
return state + 1;
case 'DECREASE': // action === 'DECREASE'일 경우
return state - 1;
case 'SET_NUMBER': // action === 'SET_NUMBER'일 경우
return action.payload;
default: // 해당 되는 경우가 없을 땐 기존 상태를 그대로 리턴
return state;
}
};
// (4) 변수 store에 createStore 메서드를 통해 store을 만든 후, createStore에 인자로 Reducer 함수를 전달한다.
const store = createStore(counterReducer);
// (3) 전역 상태 저장소 store을 사용하기 위해서는 App 컴포넌트를 Provider로 감싸준 후, props로 변수 store을 전달해준다.
root.render(
<Provider store={store}>
<App />
</Provider>
);
App.js
import React from 'react';
import './style.css';
// (1) react-redux에서 useDispatch를 불러온다.
import { useDispatch, useSelector } from 'react-redux';
// (2) Action Creater 함수 increase, decrease를 불러온다.
import { increase, decrease } from './index.js';
export default function App() {
// (3) useDispatch의 실행 값을 변수에 저장해서 dispatch 함수를 사용한다.
const dispatch = useDispatch();
console.log(dispatch) // f dispatch() 가 뜬다.
const state = useSelector((state) => state);
// (4) 이벤트 핸들러 안에서 dispatch를 통해 action 객체를 Reducer 함수로 전달한다.
const plusNum = () => {
dispatch(increase());
};
const minusNum = () => {
dispatch(decrease());
};
return (
<div className="container">
<h1>{`Count: ${state}`}</h1>
<div>
<button className="plusBtn" onClick={plusNum}>
+
</button>
<button className="minusBtn" onClick={minusNum}>
-
</button>
</div>
</div>
);
}
폴더 나누기
한 파일에 다양한 기능의 코드들을 작성하는 것은 바람직하지 않다.
앞서 구현한 Redux의 코드를 역할 별로 리팩토링 한 결과는 아래와 같다.
다른 예시
// *** Redux의 기본 구현 방식
//App.js에 수량을 +1, -1 하는 버튼이 각각 있다.
//App.js
import React from 'react';
import styled from 'styled-components';
import { useSelector, useDispatch } from 'react-redux';
export default function App() {
const number = useSelector((state) => state);
console.log(number); // 0
const dispatch = useDispatch();
const plusNum = () => {
dispatch({ type: 'Plus' });
};
const minusNum = () => {
dispatch({ type: 'Minus' });
};
return (
<Container>
<Text>{`수량 : ${number}`}</Text>
<Button onClick={plusNum}>👍</Button>
<Button onClick={minusNum}>👎</Button>
</Container>
);
}
//reducer.js
export const reducer = (initialState = 0, action) => {
let newState = initialState;
switch (action.type) {
case 'Plus':
return newState + 1;
case 'Minus':
return newState - 1;
default:
return initialState;
}
};
- newState 변수는 현재 상태값(initialState)을 복사하여 변경 가능한 변수를 만들기 위해 사용된다.
- 이렇게 함으로써, 원래의 상태값을 변경하지 않고도 새로운 값을 할당할 수 있다.
- Reducer는 순수 함수(pure function)로 작성되어야 한다. 따라서, reducer 함수 내에서 상태값을 직접 변경하는 것은 권장되지 않는다.
- 상태값을 변경하는 대신, 이전 상태값을 복사한 새로운 상태값을 만들고, 이를 새로운 상태값으로 반환하는 것이 좋다.
728x90
'FE > React' 카테고리의 다른 글
쇼핑몰 앱에서 Redux를 이용한 상태 관리 (2) (0) | 2023.04.26 |
---|---|
쇼핑몰 앱에서 Redux를 이용한 상태 관리 (1) (0) | 2023.04.26 |
상태 관리 라이브러리 Redux (0) | 2023.04.24 |
쇼핑몰 애플리케이션에서 Hooks를 이용한 상태 관리 (0) | 2023.04.24 |
Props Drilling이란? (0) | 2023.04.21 |