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.jsexport const SHOWMODAL = 'showModal'export const HIDEMODAL = 'hideModal'// src/store/actions/modal.actions.jsimport { SHOWMODAL, HIDEMODAL} from './../const/modal.const'export const show = () => ({type: SHOWMODAL})export const hide = () => ({type: HIDEMODAL})// src/store/reducers/counter.reducers.jsimport { 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-exportexport 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-exportexport 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.jsconst mapStateProps = ({ counter }) => ({ count: counter.count, a: '1'})// src/components/Modal.jsconst mapStateToProps = ({ modaler }) => { return { showState: modaler.show }}