Redux 예제 (Redux를 알아보자)
리액트를 독학하기 시작하면서 Redux도 알게돼서 스스로 이해하고 알아본 내용을 작성해봅니다. 공홈을 통해서 공부했고, 영어 번역을 제대로 하지 않아서 제가 알고있는 내용이 정확하지 않을 수 있으므로 공홈을 꼭 참고하시길 바랍니다.
Counter 예제를 만들어보자
먼저 완성된 화면부터 보자면,
위와 같고, +를 누르면 1 증가, -를 누르면 1 감소
Add Amount : 왼쪽박스에 적힌 수 만큼 증가
Add Async : 왼쪽박스에 적힌 수 만큼 Async 증가 (사용자가 지정한 Async, 여기서는 setTimeout 1000.)
Redux는 새로고침을 해도 변한 값이 유지가 된다는 장점이 있다.
Application Content
- /src
- index.js : app 시작점
- App.js : React Component의 최상단 부분이 있는 곳
- /app
- store.js : Redux store 생성자를 만듦
- /features
- /counter
- Count.js : 카운터 UI를 보여주는 React Component
- counterSlice.js : 카운터 Redux 로직
- /counter
Redux Store 생성
app/store.js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export default configureStore({
reducer: {
counter: counterReducer
}
})
React Toolkit에서 제공하는 configureStore로 Redux store을 생성함.
{counter: counterReducer} key-value 또는 alias 개념으로 생각하면된다.
즉, 여기의 counterReducer를 쓰려면 state.counter 이런식으로 불러와서 사용하면 됨.
만약 {counter: counterReducer}이 아니라 그냥 {counterReducer} 라고 쓴다면 state.counterReducer 라고 불러와서 쓰면 됨.
store가 생성됐다.
이제 어디서든 counter의 값이 변하면 여기에 저장이 될 것이다.
더 많은 Slice 사용
import { configureStore } from '@reduxjs/toolkit'
import usersReducer from '../features/users/usersSlice'
import postsReducer from '../features/posts/postsSlice'
import commentsReducer from '../features/comments/commentsSlice'
export default configureStore({
reducer: {
users: usersReducer,
posts: postsReducer,
comments: commentsReducer
}
})
Slice Reducers 및 Actions 생성
features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
increment: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1
},
decrement: state => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
}
}
})
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export const selectCount = (state) => state.counter.value;
export default counterSlice.reducer
첫번째 인트로에서 다음과 같은 세 가지의 서로 다른 버튼을 만들었던 것을 볼 수 있었다.
- {type: "counter/increment"}
- {type: "counter/decrement"}
- {type: "counter/incrementByAmount"}
Redux Toolkit은 createSlice를 제공한다. createSlice는 name과 초기값 설정을 할 수 있으며, action을 지정할 수 있다.
이 예제에서는 name: 'counter', 초기값은 0 으로 설정
reducers 내에서 수행할 action을 작성.
increment : 1증가
decrement : 1감소
incrementByAmount : value 값 만큼 증가
마지막 세 줄의 추가도 잊으면 안된다.
The React Counter Component
features/counter/Counter.js
import React, { useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import {
decrement,
increment,
incrementByAmount,
selectCount
} from './counterSlice'
import styles from './Counter.module.css'
export function Counter() {
const count = useSelector(selectCount)
const dispatch = useDispatch()
const [incrementAmount, setIncrementAmount] = useState('2')
return (
<div>
<div className={styles.row}>
<button
className={styles.button}
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
+
</button>
<span className={styles.value}>{count}</span>
<button
className={styles.button}
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
-
</button>
</div>
{/* omit additional rendering output here */}
</div>
)
}
1. useSelectore을 통해 Redux store내의 필요한 값을 가져온다. (여기서는 counter이 되겠다.)
2. useDispatch 를 사용해야지만 store 값을 변경할 수 있다. useDispatch를 사용하지 않으면 우리가 직접적으로 store 값을 변화시킬수가 없음..
3. button onClick이벤트는 counterSlice내의 기능 버튼들을 사용
마지막, Store 제공
useSelector와 useDispatch hook은 Redux store 를 호출해야 사용해야 쓸 수 있다.
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import store from './app/store'
import { Provider } from 'react-redux'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
ReactDom.render(<App />
1. import app/store.js
2. <App>을 <Provider> component 안에 감싸고, Provider에 store={store} 사용을 명시.
<Provider>를 가져와서 Redux store을 호출했고, 이제 React Components에서 useSelectore 또는 useDispatch를 쓸 수 있게됐다.
끝.
최종응용
나는 A페이지에서 어떤 값을 20으로 설정했을때, 다른 페이지 B에서도 20값을 불러와 지는지 궁금했다.
(당연히 Redux는 모든 프로젝트 내 state가 공유되므로 가능하겠지?)
1. 위 예제를 따라서 그냥 단순히 숫자 증가, 감소만 생성
2. 숫자 변경
3. 다른페이지에서 확인
재미있다 Redux!
↓Redux 예제 응용한 코드 [더보기]↓
Redux 예제 응용 코드 [더보기]
-------------------------------------------Market.js
https://redux.js.org/tutorials/essentials/part-2-app-structure