React-Redux에서 제공하는 기능을 활용하여 Counter 예제를 만들어 보면서 전역 상태관리의 흐름을 이해하자.
provider는 react-redux에서 제공하는 컴포넌트로 이를 통해 store에 접근 가능하게 만들어준다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
// redux store
import {Provider} from 'react-redux'
import {createStore} from 'redux';
import rootReducer from './modules';
import {composeWithDevTools} from 'redux-devtools-extension'
const store = createStore(rootReducer, composeWithDevTools());
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root')
);
위처럼 Provider로 App 컴포넌트를 감싸주면 App컴포넌트 내부에 존재하는 각각의 컴포넌트에서 store에 접근할 수 있게된다.
connect 함수 또한 react-redux에서 제공하는 기능으로 상태 변화가 필요한 각각의 하위 컴포넌트와 store를 연결해주는 함수다.
connect함수의 첫번째 인자로 들어가는 값으로 store에서 state값을 props로 가져와 사용할 수 있다. 컴포넌트 내에서 store의 값을 가져올 필요가 없다면 null로 대신하면 된다.
import React from 'react'
// Set Redux
import {connect} from "react-redux"
import {setDiff, increase, decrease} from '../../modules/counter'
const CounterConnect = ({number, diff}) => {
return (
<div>
<h1>{number}</h1>
<input type="number" value={diff} onChange={onChange}/>
</div>
)
}
const mapStateToProps = state => {
return {
diff: state.counter.diff,
number: state.counter.number
}
}
export default connect(mapStateToProps, null)(CounterConnect)
connect함수의 두번째 인자로 store의 상태를 바꾸기 위해 dispatch를 사용 가능하게 만들어준다.
import React from 'react'
// Set Redux
import {connect} from "react-redux"
import {setDiff, increase, decrease} from '../../modules/counter'
const CounterConnect = ({setDiff, increase, decrease, number, diff}) => {
const onChange = e => {
setDiff(parseInt(e.target.value));
}
return (
<div>
<h1>{number}</h1>
<input type="number" value={diff} onChange={onChange}/>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
)
}
const mapStateToProps = state => {
return {
diff: state.counter.diff,
number: state.counter.number
}
}
const mapDispatchToProps = (dispatch) => ({
increase: () => dispatch(increase()),
decrease: () => dispatch(decrease()),
setDiff: diff => dispatch(setDiff(diff))
})
export default connect(mapStateToProps, mapDispatchToProps)(CounterConnect)
mapDispatchToProps없이 이렇게도 표현 가능하다.
import React from 'react'
// Set Redux
import {connect} from "react-redux"
import {setDiff, increase, decrease} from '../../modules/counter'
const CounterConnect = ({setDiff, increase, decrease, number, diff}) => {
const onChange = e => {
setDiff(parseInt(e.target.value));
}
return (
<div>
<h1>{number}</h1>
<input type="number" value={diff} onChange={onChange}/>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
)
}
const mapStateToProps = state => {
return {
diff: state.counter.diff,
number: state.counter.number
}
}
export default connect(mapStateToProps, { increase, decrease, setDiff })(CounterConnect)