redux 实现弹出框案例
实现成果,点击显示按钮呈现弹出框,点击敞开按钮暗藏弹出框
- 新建弹出框组件 src/components/Modal.js, 在 index.js 中引入 app 组件,在 app 中去显示计数器和弹出框组件
function Modal ({showState, show, hide}) {
const styles = {
width: 200,
height: 200,
position: 'absolute',
top: '50%',
left: '50%',
marginTop: -100,
marginLeft: -100,
backgroundColor: 'skyblue',
}
return <div>
<button> 显示 </button>
<button> 暗藏 </button>
<div style={styles}></div>
</div>
}
- 弹出框组件显示暗藏是一个状态,所以咱们存储到 store 中,命名为 show,因为须要登程 action 来批改 store 中的状态所系咱们须要创立 modal.actions.js 文件,来存储管制显示暗藏的 action,咱们还是把显示与暗藏 aciton 的 type 定义为常量不便导入应用
// src/store/const/modal.const.js
export const SHOWMODAL = 'showModal'
export const HIDEMODAL = 'hideModal'
// src/store/actions/modal.actions.js
import {SHOWMODAL, HIDEMODAL} from './../const/modal.const'
export const show = () => ({type: SHOWMODAL})
export const hide = () => ({type: HIDEMODAL})
// src/store/reducers/counter.reducers.js
import {INCREMENT, DECREMENT} from './../const/counter.const'
import {SHOWMODAL, HIDEMODAL} from './../const/modal.const'
const initialState = {
count: 0,
// 减少管制 modal 显示暗藏显示的状态,默认为暗藏状态
show: false
}
// eslint-disable-next-line import/no-anonymous-default-export
export default (state = initialState, action) => {switch (action.type) {
case INCREMENT:
return {count: state.count + action.payload}
case DECREMENT:
return {count: state.count - action.payload}
case SHOWMODAL:
return {show: true}
case HIDEMODAL:
return {show: false}
default:
return state
}
}
- 弹框的显示暗藏状态用 display 属性管制所以咱们须要把状态映射到 props 属性中,因为 show 状态与 show 显示办法重名了,所以给 show 状态起一个别名,利用 bindActionCreators 办法把 执行 dispatch 提交 actions 的办法映射到 props 中
import React from 'react'
import {connect} from 'react-redux'
import * as modalActions from './../store/actions/modal.actions'
import {bindActionCreators} from 'redux'
function Modal ({showState, show, hide}) {
const styles = {
width: 200,
height: 200,
position: 'absolute',
top: '50%',
left: '50%',
marginTop: -100,
marginLeft: -100,
backgroundColor: 'skyblue',
// 减少管制显示暗藏的 css 款式
display: showState ? 'block' : 'none'
}
return <div>
<button onClick={show}> 显示 </button>
<button onClick={hide}> 暗藏 </button>
<div style={styles}></div>
</div>
}
// 映射显示英藏状态到 props 中
const mapStateToProps = state => {
return {showState: state.show}
}
// 把提交 actions 办法映射到组件 props 中
const mapDispacthToProps = dispatch => bindActionCreators(modalActions, dispatch)
export default connect(mapStateToProps,mapDispacthToProps)(Modal)
通过下面咱们发现在点击显示与暗藏之后计数器组件中的数字不见了,因为咱们在执行显示与暗藏的办法中并没有返回 计数器的状态所以这个状态失落掉了,咱们须要在更改状态的时候去补上原有的状态
- 补上原有状态
export default (state = initialState, action) => {switch (action.type) {
case INCREMENT:
return {
...state,
count: state.count + action.payload
}
case DECREMENT:
return {
...state,
count: state.count - action.payload
}
case SHOWMODAL:
return {
...state,
show: true
}
case HIDEMODAL:
return {
...state,
show: false
}
default:
return state
}
}
这个时候咱们的计数器与弹出框组件都曾经失常了,然而咱们发现 reducer 函数随着 actions 动作越来越多变的越来越臃肿,在状态越来越多当前将会变得无奈保护
拆分 reducer 函数
在计数器与弹出框案例中,在 reducer 函数中,咱们既匹配到了计数器案例中的 actions,又匹配到了弹出框案例中的 actions 这样 reducer 中的代码将会越来越宏大,越来越臃肿,所以咱们接下来拆分 reducer,拆分 reducer 咱们须要用到 combineReducers 办法,这个办法要求咱们传递一个对象 这个对象是状态对象,返回值是合并后的 reducer
- 创立 src/store/reducers/modal.reducers.js 文件,把弹出框的 reducer 抽离进去
import {SHOWMODAL, HIDEMODAL} from './../const/modal.const'
const initialState = {show: false}
// eslint-disable-next-line import/no-anonymous-default-export
export default (state = initialState, action) => {switch (action.type) {
case SHOWMODAL:
return {
...state,
show: true
}
case HIDEMODAL:
return {
...state,
show: false
}
default:
return state
}
}
- 创立 src/store/reducers/root.reducers.js 文件,用于合并计数器与弹出框的 reducer
import {combineReducers} from 'redux'
import CounterReducers from './counter.reducers'
import ModalReducers from './modal.reducers'
// 要求咱们传递一个对象 这个对象是状态对象
// 这样写了之后 状态的构造将是这样 counter: {count: 0} modaler: {show: false}
export default combineReducers({
counter: CounterReducers,
modaler: ModalReducers
})
- 因为应用 combineReducers 合并 reducer 的时候扭转了 state 的构造所以咱们须要在组件中去更改获取 state 的形式
// src/components/Count.js
const mapStateProps = ({counter}) => ({
count: counter.count,
a: '1'
})
// src/components/Modal.js
const mapStateToProps = ({modaler}) => {
return {showState: modaler.show}
}