使用React-Redux进行应用数据的管理
我们想引入Redux进行数据管理,顺便把之前的focused也放进去。
1.首先导入redux相关的两个模块
cnpm install --save redux react-redux
2.编写redux的一些基础文件
//===>src/store/index.js
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store
//===>src/reducer.js
const defaultState = {
focused: false
}
export default (state = defaultState, action) => {
if (action.type === 'search_focus') {
return {
focused: true
}
}
if (action.type === 'search_blur') {
return {
focused: false
}
}
return state
}
3.修改Header组件,把之前focused放到redux中进行管理
//===>src/common/header/index.js
import React, { Fragment } from 'react'
import { CSSTransition } from 'react-transition-group'
import {
HeaderWrapper,
Logo,
Nav,
NavItem,
SearchWrapper,
NavSearch,
Addition,
Button
} from './style'
import { IconFontStyle } from '../../statics/iconfont/iconfont';
import { connect } from 'react-redux'
const Header = (props) => {
return (
<Fragment>
<IconFontStyle />
<HeaderWrapper>
<Logo />
<Nav>
<NavItem className='left'>首页</NavItem>
<NavItem className='left'>下载App</NavItem>
<NavItem className='right'>登录</NavItem>
<NavItem className='right'>
<span className="iconfont"></span>
</NavItem>
<SearchWrapper>
<CSSTransition
in={props.focused}
timeout={200}
classNames="slide">
<NavSearch
className={props.focused ? 'focused' : ''}
onFocus={props.handleInputFocus}
onBlur={props.handleInputBlur}>
</NavSearch>
</CSSTransition>
<span className={props.focused ? 'focused iconfont' : 'iconfont'}></span>
</SearchWrapper>
<Addition>
<Button className='writting'>
<span className="iconfont"></span>写文章
</Button>
<Button className='reg'>注册</Button>
</Addition>
</Nav>
</HeaderWrapper>
</Fragment>
)
}
const mapStateToProps = (state) => {
return {
focused: state.focused
}
}
const mapDispatchToProps = (dispatch) => {
return {
handleInputFocus() {
const action = {
type: 'search_focus'
}
dispatch(action)
},
handleInputBlur() {
const action = {
type: 'search_blur'
}
dispatch(action)
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Header)
效果不变。
使用combineReducers完成对数据的拆分管理
首先我们先用redux-devtools-extension去做下监控
//===>src/store/index.js
import { createStore, compose } from 'redux'
import reducer from './reducer'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers());
export default store
我们想把reducer对组件们的操作,拆分到每一个组件对应的文件夹中。
1.新建header组件的reducer文件
//===>src/common/header/store/index.js
import reducer from './reducer'
export { reducer }
//===>src/common/header/store/reducer.js
const defaultState = {
focused: false
}
export default (state = defaultState, action) => {
if (action.type === 'search_focus') {
return {
focused: true
}
}
if (action.type === 'search_blur') {
return {
focused: false
}
}
return state
}
2.用store把他们管理起来
//===>src/store/reducer.js
import { combineReducers } from 'redux'
import {reducer as headerReducer} from '../common/header/store'
const reducer = combineReducers({
header: headerReducer
})
export default reducer
3.最后,千万不要忘记,我们把数据拆分了,那要改一下组件中找属性的路径
//===>src/common/header/index.js
...
const mapStateToProps = (state) => {
return {
focused: state.header.focused
}
}
...
actionCreators与constants的拆分
这一小节,我们的目标是,整理header的store。
任务一:在header文件夹下的store中,暴露出store相关的内容,以便Header组件只引入store的index.js就可以解构出reducer、constants等内容。
//===>src/common/header/store/index.js
import reducer from './reducer'
import * as actionCreators from './actionCreators'
import * as constants from './constants'
export { reducer, actionCreators, constants }
任务二:创建actionCreators并使用。
1.编写全局变量
//===>src/common/header/store/constants.js
export const SEARCH_FOCUS = 'header/SEARCH_FOCUS'
export const SEARCH_BLUR = 'header/SEARCH_BLUR'
2.编写actionCreators
//===>src/common/header/store/actionCreators.js
import * as constants from './constants'
export const searchFocus = () => ({
type: constants.SEARCH_FOCUS
})
export const searchBlur = () => ({
type: constants.SEARCH_BLUR
})
3.修改header的reducer,引入刚才定义的全局变量
//===>src/common/header/store/reducer.js
import * as constants from './constants'
const defaultState = {
focused: false
}
export default (state = defaultState, action) => {
if (action.type === constants.SEARCH_FOCUS) {
return {
focused: true
}
}
if (action.type === constants.SEARCH_BLUR) {
return {
focused: false
}
}
return state
}
4.在Header组件中修改action的分发
import { actionCreators } from './store';
...
const mapDispatchToProps = (dispatch) => {
return {
handleInputFocus() {
dispatch(actionCreators.searchFocus())
},
handleInputBlur() {
dispatch(actionCreators.searchBlur())
}
}
}
...
使用Immutable.js来管理store中的数据
在reducer中,我们不希望修改state的数据,而是希望返回一个新的数据。所以我们引入了Immutable。
1.引入第三方模块Immutable
npm install --save immutable
2.修改reducer,把state包装成immutable类型
immutable对象的set方法,会结合之前的immediate对象的值和设置的值,返回一个全新的对象。
//===>src/common/header/store/reducer.js
import * as constants from './constants'
import { fromJS } from 'immutable'
const defaultState = fromJS({
focused: false
})
export default (state = defaultState, action) => {
if (action.type === constants.SEARCH_FOCUS) {
return state.set('focused', true)
}
if (action.type === constants.SEARCH_BLUR) {
return state.set('focused', false)
}
return state
}
3.因为state.header已经是immutable类型的量了,我们就不能用传统方法去改变他的值了。
//===>src/common/header/index.js
...
const mapStateToProps = (state) => {
return {
focused: state.header.get('focused')
}
}
...
这样就可以了。
使用redux-immutable统一数据格式
上一小节中,第三步focused: state.header.get('focused') 这个写法很奇怪,state对象是个普通js对象,但state.header却是一个immutable对下对象。这一小节的我们的目标是,把state统一成immutable对象。
1.导入redux-immutable
npm install --save redux-immutable
2.修改combineReducers的引入
//===>src/store/reducer.js
//import { combineReducers } from 'redux' 把这个改成下面这个,它里面的state就变成immutable类型的对象了。
import { combineReducers } from 'redux-immutable'
...
3.因为state已经是immutable类型的量了,我们就不能用传统方法去改变他的值了。
//===>src/common/header/index.js
...
const mapStateToProps = (state) => {
return {
// focused: state.get('header').get('focused')
focused: state.getIn(['header', 'focused'])
}
}
...
网友评论