일반적인 구조로는:
actions, constants,reducer 등 세개의 디렉토리를 만들어 그 안의 기능별로 따로 분리 해서 한다.
Ducks pattern
ducks 패턴은 액션타입,액션 생성함수, 리듀서 함수를 기능별로 파일 하나에 몰아서 다 적상한다고 한다..
위중에서 어느게 맞고 장단점이 뭔지는 추후에 한번 파볼 예정이다.
김민준- 리액트를 다루는 기술에서는 DUCKS 패턴을 사용하여 Counter 를 적용하였다.
Counter JS
const INCREASE = "counter/INCREASE"
const DECREASE = "counter/DECREASE"
//ACTIONS
export const increase = () => ({ type: INCREASE })
export const decrease = () => ({ type: DECREASE })
//Reducer
const initialState = {
number: 0,
}
function counter(state = initialState, action) {
switch (action.type) {
case INCREASE:
return {
number: state.number + 1,
}
case DECREASE:
return {
number: state.number - 1,
}
default:
return state
}
}
export default counter
import { combineReducers } from "redux"
import counter from "./counter"
import todos from "./todos"
const rootReducer = combineReducers({
counter,
todos,
})
export default rootReducer
createStore 함수를 사용하여 스토어를 만들때 리듀서는 하나 여야 한다. 그래서 여러 리듀서가 있으면 하나로 합쳐 줘야 한다.
Store만들기
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
import { createStore } from "redux"
import { Provider } from "react-redux"
import rootReducer from "./modules"
import { composeWithDevTools } from "redux-devtools-extension"
const store = createStore(rootReducer, composeWithDevTools())
ReactDOM.render(
<Provider store={store}>
<React.StrictMode>
<App />
</React.StrictMode>
</Provider>,
document.getElementById("root")
)
rootReducer 를 import 하여 createStore 함수안에 넣어준다.
Provider 컴포넌트를 사용하여 프로젝트에 리덕스를 적용한다.
Redux DevTools(리덕스 개발자 도구) 를 크롬확장 프로그램에 설치함.
원래는
const store=createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__&&window.__REDUX_DEVTOOLS_EXTENSION()
으로 적용...하지만..
패키지를 설치하여 적용하면 코드가 훨씬 깔금해진다.
yarn add redux-devtools-extension
npm i redux-devtools-extension
둘중에 하나 로 설치하고..
import { composeWithDevTools } from "redux-devtools-extension"
const store = createStore(rootReducer, composeWithDevTools())
로 적용하면 된다.
리덕스 스토에 접근하여 원하는 상태를 받아 오고, 액션을 dispatch(실행) 하기 위해서는 컨테이너 컴포넌트? 를 만들어야 합니다.
컴포넌트 를 리덕스 Store 와 연동하려면 react-redux에서 제공하는 connect 함수를 사용해야 한다.
export default connect(mapStateToProps, mapDispatchToProps)(CountContainer)
mapStateToProps 는 리덕스 상태를 컴포넌트 안의 props로 넘겨주기 위해 설정하는 함수이고.
mapDispatchToProps 는 리덕스 액션 함수를 props로 넘겨주기 위해 사용해야 하는 함수이다.
import React from "react"
import Counter from "../components/Counter"
import { connect } from "react-redux"
import { increase, decrease } from "../modules/counter"
const CountContainer = ({ number, increase, decrease }) => {
return <Counter number={number} onIncrease={increase} onDecrease={decrease} />
}
const mapStateToProps = (state) => ({
number: state.counter.number,
})
const mapDispatchToProps = (dispatch) => ({
increase: () => {
dispatch(increase())
},
decrease: () => {
dispatch(decrease())
},
})
export default connect(mapStateToProps, mapDispatchToProps)(CountContainer)
일반적으로는 mapStateToProps 와 mapDisPatchToProps 를 미리 선언핸 놓고 사용하지만..
connect 내부에 함수 상태로 선언해도 문제가 되지 않는다.
export default connect(
(state) => ({
number: state.counter.number,
}),
{
increase,
decrease,
}
)(CountContainer)
export default connect(
(state) => ({
number: state.counter.number,
}),
{
increase,
decrease,
}
)(CountContainer)
컴포넌트에 액션을 디스패치 하기 위해서 각 액션 생성 함수를 호출하고 dispatch로 감싸는 작업이 조금 번거로울수도 있다고 한다. 특히 액션 함수가 많아질수록 더욱 그렇다고 한다.
이럴때 bindActionCreators 유틸 함수를 사용하면 간단해 진다고 함.
import { bindActionCreators } from "redux"
추가 하고..
export default connect(
(state) => ({
number: state.counter.number,
}),
(dispatch) =>
bindActionCreators(
{
increase,
decrease,
},
dispatch
)
)(CountContainer)
로 진행한다고 한다.