Cart 컴포넌트 생성
부트스트랩의 Table을 이용해서 간단한 장바구니 컴포넌트를 생성해보자.
//App.ts
<Route path='/cart' element = {<Cart></Cart>}></Route>
function Cart(){
return(
<Table striped bordered hover>
<thead>
<tr>
<th>#</th>
<th>상품명</th>
<th>수량</th>
<th>변경하기</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>아메리카노</td>
<td>1</td>
<td><button>변경</button></td>
</tr>
<tr>
<td>2</td>
<td>카페라떼</td>
<td>1</td>
<td><button>변경</button></td>
</tr>
</tbody>
</Table>
)
}
Redux를 사용하는 이유
커피 상태는 App Detail Cart 모두에서 사용된다. 이를 프롭스로 전달하는 것도 가능하지만 컴포넌트가 중첩되어있어서 불편하다. 이를 위해 Context Api 방법을 배웠지만 더 좋은 라이브러리인 Redux가 있다. Redux를 사용하면 state가 저장되어있는 파일을 만들고 그곳에 상태들을 저장한다. 그렇게 하면 모든 컴포넌트에서 접근하여 사용할 수 있다.
Redux 설치
npm install @reduxjs/toolkit react-redux
npm 명령어를 통해 리덕스를 설치한 후 src 폴더에 store.tsx 파일을 만들어준다. 이 파일은 상태들을 담아줄 통같은 존재이다.
그 후 몇가지 세팅을 해주어야한다.
//store.tsx
import {configureStore} from "@reduxjs/toolkit";
export default configureStore({
reducer : {
}
})
//index.tsx
import store from './store';
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<Provider store = {store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</React.StrictMode>
);
index.tsx 에서도 몇가지 세팅을 해주는데 store를 import해주고 Provider도 import 해준다. 그후 App 부분을 Provider로 감싸주고 보관함 설정을 해주면 끝이다.
store에 상태 보관하기
//store.tsx
import {configureStore, createSlice} from "@reduxjs/toolkit";
let user = createSlice({
name : 'user',
initialState : '홍길동',
reducers : {}
})
let stock = createSlice({
name : 'stock',
initialState : [100,200,300],
reducers : {}
})
export default configureStore({
reducer : {
user : user.reducer,
stock : stock.reducer,
}
})
createSlice 함수를 사용해서 state를 생성하고 등록해준다.
//Cart.tsx
import { useSelector } from "react-redux";\
let data = useSelector((state)=>{
return state;
})
console.log(data);
다른 파일에서는 useSelector를 사용해서 상태를 가져올 수 있다.
store 데이터 바인딩하기
store에 커피 정보를 저장하고 바인딩해서 사용해보겠다.
//store.tsx
export interface CartItem{
id : number;
name: string;
count: number;
}
export interface CartArray{
cart : CartItem[];
}
let cart = createSlice({
name : 'cart',
initialState : {
cart: [
{id : 0, name: '아메리카노', count : 1},
{id : 1, name: '카페라떼', count : 1}
]} as CartArray,
reducers : {}
})
store에 저장할때 타입스크립트에 맞게 타입과 타입배열을 선언해서 사용한다. as 는 type Assertion 키워드로 변수나 오브젝트의 타입을 지정해 줄 때 사용한다.
//Cart.tsx
interface CartState{
cart : CartArray;
}
let cartState = useSelector((state : CartState)=>{
return state;
})
CartState 타입을 선언후 가져온다.
{
cartState.cart.cart.map((item, idx)=>{
return (
<tr key={idx}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.count}</td>
<td><button>변경</button></td>
</tr>
)
})
}
그 후 배열 map 함수를 사용해 처리해 줄 수 있다.
store 데이터 변경하기
store 에 저장된 데이터를 수정하는 것은 다음과 같다.
//store.tsx
let user = createSlice({
name : 'user',
initialState : '홍길동',
reducers : {
changeName(){
return '리덕스'
}
}
})
export let {changeName} = user.actions;
리덕스의 데이터 수정은 수정함수를 store에 구현하는 방식으로 이루어진다. 그 후 actions 를 통해 export 해준다. actions 는 함수들을 다 반환하는 프로퍼티이고, 비구조화를 통해 받아냈다.
import {changeName} from "../store";
import { useSelector, useDispatch } from "react-redux";
let dispatch = useDispatch();
이때 함수를 바로 콜할수는 없고 useDispatch 라는 것을 사용해서 불러줘야한다.
<button onClick={()=>{
dispatch(changeName());
}}>이름변경</button>
<div>{cartState.user}</div>
변경함수를 사용하는 예제 코드이다. dispatch 로 함수를 감싸주어야 제대로 작동한다.
리덕스가 복잡한 이유는 무엇일까? 만약 각 컴포넌트에서 직접 store에 접근해 데이터를 변경하면 오류가 발생했을 경우 그 원인을 찾기가 쉽지 않을 것이다. 의존성이 있는 컴포넌트를 모두 살펴봐야 하기 때문이다. 하지만 수정함수를 만들어 두고 각 컴포넌트에서 store에 부탁하는 방식으로 구현하면 오류가 나도 store 하나만 보면 되니까 간편하다. 즉, 변경의 주도권을 store가 가지는것이 효율적이라는 것이다.
store 데이터가 array 나 object 일 때 변경하는 법
배열이나 객체일 때도 비슷한 방식으로 변경할 수 있다.
let user = createSlice({
name : 'user',
initialState : {name: '홍길동', age: 20},
reducers : {
changeName(){
return {name: '리덕스', age: 20}
}
}
})
initialState 를 객체형태로 바꾸었다. 이를 변경하는 함수에서 새로운 객체를 return 할 수 있다. 하지만 새로운 객체를 리턴하는 방식은 다소 비효율적이다. 그래서 다음과 같이 코드를 수정할 수 있다.
changeName(state){
state.name = '리덕스';
}
함수의 인자로 state를 받아오고 그 state를 직접 수정하는 방식이다. 이렇게 하면 더 간단하고 효율적인 코드가 완성된다.
후기
redux의 사용법에 대해 본격적으로 알아보았다. 다소 복잡하지만 프로젝트가 복잡해지면 유용하게 사용할 수 있을 것 같다.
키워드: 프로그래머스 데브코스, 국비지원교육, 코딩부트캠프
'프로그래머스 풀스택 데브코스 > 데브코스 TIL' 카테고리의 다른 글
웹 풀사이클 데브코스 TIL 57일차 (0) | 2024.02.13 |
---|---|
웹 풀사이클 데브코스 TIL 56일차 (0) | 2024.02.11 |
웹 풀사이클 데브코스 TIL 54일차 (0) | 2024.02.06 |
웹 풀사이클 데브코스 TIL 53일차 (0) | 2024.02.05 |
웹 풀사이클 데브코스 TIL 52일차 (0) | 2024.02.03 |