티스토리 뷰
Redux를 사용하면 컴포넌트들이 props없이 state 공유가능
Redux 설치
❗ package.json에서 react와 react-dom의 버전이 18.1.0이상만 가능!
- 터미널에서 하던작업 멈추고( Ctrl+c)
npm install @reduxjs/toolkit react-redux
Redux 세팅
1. src폴더 안에 store.js 파일 생성 - state를 보관할 곳
- store.js 파일 안에 아래 코드 작성
import { configureStore } from '@reduxjs/toolkit'
export default configureStore({
reducer: { }
})
2. index.js에서 아래 코드 작성
<Provider store={store}>
- 전체 코드
import store from './store.js'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// <React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
// </React.StrictMode>
);
-> 여기까지 세팅하면 이제 App 파일과 그 자식들은 store.js에 있는 state 전부 사용 가능
state 사용하기
- Redux store에 state 보관하는 방법
- creacteSlice를 사용해서 변수 지정, 키와 값 지정
- reducer 안에 사용할 변수 넣기
import { configureStore, createSlice } from '@reduxjs/toolkit'
/* Redux store에 state 보관하는 방법 */
let user = createSlice({ // useState 역할
name: 'user',
initialState : 'Kim'
})
let stock = createSlice({ // useState 역할
name: 'stock',
initialState :[
{id : 0, name : 'White and Black', count : 2},
{id : 2, name : 'Grey Yordan', count : 1}
]
})
/* ! Redux store 안에 모두 넣진 말기. 컴포넌트 간 공유가 필요없으면 useState() 사용 */
export default configureStore({
reducer: {
user : user.reducer,
stock : stock.reducer
}
})
- Redux store에서 state 가져오는 방법
function Cart(){
/* Redux store에서 state 가져옴 */
// let state = useSelector((state) => { return state }) // return하는 것만 가져다 씀
let state = useSelector((state) => state ) // 중괄호 return은 축약가능
console.log(state) // ex) return state.stock이면 state = stock 값만 나옴
return (
{state.stock[0].name} {/* store에서 가져온 값 바인딩 */}
)
}
export default Cart
state 변경하기
- state를 수정하는 함수를 만듦
- 수정이 필요할 때 해당 함수를 실행하달라고 store.js에 요청- store.js에 1번에서 만든 함수 export
- 만든 함수가 필요한 곳에서 store.js로 요청을 보내주는 함수 useDispatch()로 변수를 만들어줌
- 만든 함수가 필요한 곳에 3번에서만든변수명(state변경함수())
- store.js
let user = createSlice({
name : 'user',
initialState : 'Kim',
reducers : { // state 변경 1. 변경함수 만들기
changeName(state){ // 여기에 export를 붙일 수는 없음 -> 밖으로 빼기
return 'John' + state
}
}
})
export let { changeName } = user.actions // 2. export 해주기. 위에서 만든 변경함수가 object 자료형식으로 남음
// 여기서 user.actions의 user는 1번줄의 user
* action = state 변경함수
- Cart.js
import { changeName } from '../store';
function Cart(){
let state = useSelector((state) => state )
let dispatch = useDispatch() // store.js로 요청을 보내주는 함수
return (
<div>
{ state.user }의 장바구니
<button onClick={() => {
dispatch(changeName()) // dispatch(state변경함수()
}}>+</button>
</div>
)
}
export default Cart
state 변경함수의 장점
- 버그 발생시 원인파악이 쉬움( 컴포넌트가 HTML을 수정하면 모든 컴포넌트를 다 뒤져야함)
state가 array/object인 경우
- return { 키 : '값' } 적어서 직접 값을 갈아끼우거나
- state.키 = '값' 적어서 해당 키값만 변경(immer.js 라이브러리가 알아서 해줌)
let user = createSlice({
name : 'user',
initialState : { name : 'Kim', age : 20 }, // Q. state가 array/object인 경우 변경방법은?
reducers : {
changeName(state){
// return { name : 'Park', age : 20 }
state.name = 'Park'
}
}
})
export let { changeName } = user.actions
state 변경함수에 파라미터 넣기
- store.js
let stock = createSlice({
name : 'stock',
initialState :[
{id : 0, name : 'White and Black', count : 2},
{id : 2, name : 'Grey Yordan', count : 1}
],
reducers : {
increase(state){
state[0].count += 1
},
increase2(state, a){
state[1].count += a.payload // payload를 붙여야 해당 함수의 파라미터값이 제대로 들어감
}
}
})
export let { increase, increase2 } = stock.actions
* dispatch(increase2(10)) = dispatch가 increase2란 메세지에 10이란 화물도 같이 보낸다는 의미
- Cart.js
import { changeName, increase, increase2 } from '../store';
function Cart(){
let state = useSelector((state) => state )
let dispatch = useDispatch() // store.js로 요청을 보내주는 함수
return (
<div>
<button onClick={() => {
dispatch(increase2(10))
}}>+10버튼</button>
</div>
)
}
export default Cart
코드가 길어질 때 코드 분리하기
(코드 분리 전)
- store.js
import { configureStore, createSlice } from '@reduxjs/toolkit'
let user = createSlice({
name : 'user',
initialState : 'Kim',
reducers : {
changeName(state){
return 'John' + state
}
}
})
export let { changeName } = user.actions
- Cart.js
import { changeName, increase, increase2 } from './../store';
(코드 분리 후)
-store.js
import { configureStore, createSlice } from '@reduxjs/toolkit'
import user from './store/userSlice.js'
- userSlice.js
import { createSlice } from '@reduxjs/toolkit'
let user = createSlice({
name : 'user',
initialState : { name : 'Kim', age : 20 },
reducers : {
changeName(state){
// return { name : 'Park', age : 20 }
state.name = 'Park'
}
}
})
export let { changeName } = user.actions
export default user
- Cart.js
import { changeName } from './../store/userSlice';
import { increase, increase2 } from './../store';
📘 장바구니 > 추가 버튼 클릭 시 상품 수량 증가
- 상품 추가 버튼을 눌렀을 때 해당 상품의 수량이 증가해야함
- 새로 정렬 됐을 경우(ex) 오름차순 내림차순 가격순 이름순...) index 번호가 바뀌기 때문에 클릭한 상품id와 상품data에 있는 상품 id가 동일한 경우 해당 상품의 수량이 증가하도록 해야함
- Cart.js
import { Table } from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import { increase3 } from './../store';
function Cart(){
let state = useSelector((state) => state )
let dispatch = useDispatch()
return (
<div>
<Table>
<thead>
<tr>
<th>#</th>
<th>상품명</th>
<th>수량</th>
<th>변경하기</th>
</tr>
</thead>
<tbody>
{
state.stock.map((a, i) => {
return (
<tr key={i}>
<td>{state.stock[i].id}</td>
<td>{state.stock[i].name}</td>
<td>{state.stock[i].count}</td>
<td>
<button onClick={() => {
const stockId = state.stock[i].id
dispatch(increase3(stockId))
}}>+</button>
</td>
</tr>
)
})
}
</tbody>
</Table>
</div>
)
}
export default Cart
- store.js
import { configureStore, createSlice } from '@reduxjs/toolkit'
import user from './store/userSlice.js'
let stock = createSlice({
name : 'stock',
initialState :[
{id : 0, name : 'White and Black', count : 2},
{id : 2, name : 'Grey Yordan', count : 1}
],
reducers : {
increase3(state, action){
let stockId = state.findIndex((data) => { return data.id === action.payload })
state[stockId].count++
}
}
})
export let { increase3 } = stock.actions
export default configureStore({
reducer: {
user : user.reducer,
stock : stock.reducer
}
})
'Library | Framework > React JS' 카테고리의 다른 글
| [React] React-Query (0) | 2022.11.10 |
|---|---|
| [React] localStorage (0) | 2022.11.09 |
| [React] Context API (0) | 2022.11.05 |
| [React] AJAX, 서버와 통신 (0) | 2022.11.04 |
| [React] Lifecycle, useEffect (0) | 2022.11.03 |
댓글
