// pakage.json
{
"name": "reduxtest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"babel": {
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
},
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"@babel/cli": "^7.10.5",
"@babel/core": "^7.10.5",
"@babel/preset-env": "^7.10.4",
"@babel/preset-react": "^7.10.4",
"babel-loader": "^8.1.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.1",
"redux": "^4.0.5",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
}
}
// webpack.config.js
module.exports = {
entry: '.\\app.jsx',
output: {
path: __dirname,
filename: 'index.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude:/(node_modules)/,
use: ['babel-loader']
}
]
}
}
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>redux</title>
</head>
<body>
<div id="redux"></div>
</body>
<script src="./index.js"></script>
</html>
// BReducer.js
const TEST = 'TEST'
// 액션 생성 함수
export const test = (value) => ({
type: TEST,
value: value
})
//초기 상태
const initialState = {
value: 'initialState',
}
// 상태와 액션을 인자로 받아 새로운 상태를 생성하는 리듀서
export default (state = initialState, action) => {
switch (action.type) {
case TEST:
return { value: action.value }
default:
return { value: 'default' }
}
}
// store.js
import { createStore } from 'redux'
import BReducer from './BReducer.js'
// Provider 컴포넌트의 store 속성에 들어갈 store 생성
const store = createStore(BReducer)
// 다수의 리듀서인 경우 combineReducer 이용
export default store
// App.jsx
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import A from './A.jsx'
import C from './C.jsx'
import store from './store.js'
class App extends React.Component {
render() {
return (
// 이제 store의 값들은 각 컴포넌트들의 this.props로 접근할 수 있게 된다.
<Provider store={store}>
<A />
<C />
</Provider>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('redux')
)
// A.jsx
import React from 'react'
import B from './B.jsx'
class A extends React.Component {
render() {
return (
<div>
A
<B />
</div>
)
}
}
export default A
// B.jsx
import React from 'react'
import { connect } from 'react-redux'
import store from './store.js'
import * as BReducer from './BReducer'
class B extends React.Component {
constructor(props) {
super(props)
// input 엘리멘트의 value 접근을 위한 ref 생성
this.input = React.createRef()
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
// current를 통해 속성 값 접근 가능
let inputValue = this.input.current.value
// 아래의 mapping 된 test 함수를 실행시킨다
this.props.test(inputValue)
}
render() {
return (
<div>
B
<input ref={this.input} type="text"></input>
<button onClick={this.handleClick}>render</button>
</div>
)
}
}
const mapDispatchToProps = (dispatch) => ({
test: (value) => dispatch(BReducer.test(value))
})
export default connect(
null,
mapDispatchToProps
)(B)
// C.jsx
import React from 'react'
import D from './D.jsx'
class C extends React.Component {
render() {
return (
<div>
C
<D />
</div>
)
}
}
export default C
// D.jsx
import React from 'react'
import E from './E.jsx'
class D extends React.Component {
render() {
return (
<div>
D
<E />
</div>
)
}
}
export default D
// E.jsx
import React from 'react'
import { connect } from 'react-redux'
class E extends React.Component {
render() {
// mapping 된 value 값을 store에서 가져옴
let value = this.props.value
return (
<div>
E
{value}
</div>
)
}
}
const mapStateToProps = (state) => ({
value: state.value
})
export default connect(
mapStateToProps,
null
)(E)
참고 자료
'react' 카테고리의 다른 글
useContext 실습 (0) | 2020.09.16 |
---|---|
useMemo 실습 (0) | 2020.09.16 |
hooks에서 useState가 const로 선언되는 이유 (0) | 2020.09.07 |
router 실습 (0) | 2020.07.08 |