使用 redux 一般使用 redux 和 react-redux
- redux 提供 action、reducer、store
- react-redux 负责提供 Provider、connect
npm install --save redux
npm install --save react-redux
案例
代码结构:
src
|_ index.js
|_ redux
|_ action-types.js
|_ actions.js
|_ reducers.js
|_ store.js
|_ pages
|_ CounterPanel.js
|_ CounterItem.js
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import CounterPanel from './pages/CounterPanel'
import store from './redux/store'
import {Provider} from 'react-redux'
ReactDOM.render(
<Provider store={store}>
{
console.log('index.js:', store.getState())
}
<CounterPanel />
</Provider>
, document.querySelector('#root')
action-types.js
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
actions.js
/**
* action creator 返回的是 action
*/
import * as ActionTypes from './action-types'
export const increment = (caption) => ({
type: ActionTypes.INCREMENT,
caption
})
export const decrement = (caption) => ({
type: ActionTypes.DECREMENT,
caption
})
reducers.js
import * as ActionTypes from './action-types'
export default (state, action) => {
console.log('reducers.js', state)
const {caption} = action
switch (action.type) {
case ActionTypes.INCREMENT:
console.log('reducers.js', action)
return {...state, [caption]: state[caption]+1}
case ActionTypes.DECREMENT:
return {...state, [caption]: state[caption]-1}
default:
return state
}
}
store.js
import {createStore} from 'redux'
import reducer from './reducers'
const initState = {
'first': 0,
'second': 2,
'third': 5
}
const store = createStore(reducer, initState)
console.log('store.js:', store.getState())
export default store
CounterItem.js
import React, {Component} from 'react'
import {connect} from 'react-redux'
import PropTypes from 'prop-types'
import * as Actions from '../redux/actions'
class CounterItem extends Component {
static propTypes = {
caption: PropTypes.string.isRequired
}
render () {
return (
<div>
<button onClick={this.props.increment}>+</button>
<button onClick={this.props.decrement}>-</button>
<span>计数:{this.props.count}</span>
</div>
)
}
}
/**
*
* @param {*} state 是 redux 维护的对象
* @param {*} ownProps 是 父组件 传递过来的 props
*/
const mapStateToProps = function (state, ownProps) {
console.log(ownProps)
console.log(state)
return {
count: state[ownProps.caption]
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
increment: () => {
dispatch(Actions.increment(ownProps.caption))
},
decrement: () => {
dispatch(Actions.decrement(ownProps.caption))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(CounterItem)
CounterPanel.js
import React, {Component} from 'react'
import {connect} from 'react-redux'
import CounterItem from './CounterItem'
class CounterPanel extends Component {
render () {
return (
<div>
<CounterItem caption='first' />
<CounterItem caption='second' />
<CounterItem caption='third' />
</div>
)
}
}
const mapSatesToProps = (state) => {
console.log(state)
return {}
}
export default connect(mapSatesToProps)(CounterPanel)