解決reducer不能直接'修改'state的問題
雖然immutable看起來直接修改,實際上是返回了一個新的immutable對象
1、安裝
cnpm install immutable --save
2、引入
import {fromJS,List} from 'immutable' 還有Map和List等類型,fromJS是爲對象準備的
3、將對象狀態改變成immutable對象
xx=fromJS({
鍵值對
})
對象內的數組/對象也會同時被轉換成immutable對象,記得使用時區分
3.5數據格式轉換
在使用immutable來管理狀態後,所有的數據格式都應該是immutable對象
!!!往immutable對象內存儲數組等數據的時候,要先fromJS(x)轉換成immutable對象
fromJS(x); 能將數據及其內層全轉換成immutable對象,能用其他類型轉換的,都能使用fromJS
List(x); 轉換成immutable數組類型對象,只能轉換最外層,內層數據不能轉換
4、修改immutable狀態
方式一:
xx.set('鍵名',值)
支持鏈式調用:xx.set('鍵名',值).set('鍵名',值)...
方式二:
xx.merge({
鍵值對
})
5、設置reducer返回state
6、組件中獲取狀態
獲取到immutable對象後,調用.get('鍵名')獲取,.getIn(['x','xx']); 能獲取x內的xx
支持鏈式調用,鏈式調用和getIn效果相同
如:this.props.state.get('xx')
代碼示例:
reducer.js
import {SEARCH_FOCUS,SEARCH_BLUR,CHANGE_LIST,MOUSE_ENTER,MOUSE_LEAVE,CHANGE_PAGE} from './action-type'
import {fromJS} from 'immutable'
const initState=fromJS({
focused:false,
mouseIn:false,
list:[],
page:1,
totalPage:1
})
export default (state=initState,action)=>{
switch(action.type)
{
case SEARCH_FOCUS:
return state.set('focused',true);
case SEARCH_BLUR:
return state.set('focused',false);
case CHANGE_LIST:
return state.merge({
'list':action.data,
'totalPage':action.totalPage
})
case MOUSE_ENTER:
return state.set('mouseIn',true);
case MOUSE_LEAVE:
return state.set('mouseIn',false);
case CHANGE_PAGE:
if(state.get('page')<state.get('totalPage'))
{
return state.set('page',state.get('page')+1);
}else{
return state.set('page',1);
}
default:
return state
}
}
組件使用:
import React,{Component} from 'react'
import { CSSTransition } from 'react-transition-group';
import {connect} from 'react-redux'
import * as action from '../../store/actions'
import {
HeaderWrapper,
Logo,
Nav,
NavItem,
NavSearch,
Addition,
Button,
SearchWrapper
} from './style'
class App extends Component{
// state={
// focused:false
// }
focus=()=>{
this.setState({
focused:true
})
}
blur=()=>{
this.setState({
focused:false
})
}
render()
{
return(
<HeaderWrapper>
<Logo />
<Nav>
<NavItem className='left active'>首頁 <span className='h'> 嗷嗷</span></NavItem>
<NavItem className='left'>下載App</NavItem>
<NavItem className='right'>登錄</NavItem>
<NavItem className='right'>
<i className="iconfont"></i>
</NavItem>
<SearchWrapper>
<CSSTransition
in={this.props.state.get('focused')}
timeout={2000}
classNames="slide"
>
<NavSearch
className={this.props.state.get('focused') ? 'focused':''}
onFocus={this.props.handleInputFocus}
onBlur={this.props.handleInputBlur}
/>
</CSSTransition>
<i className={this.props.state.get('focused') ? 'focused iconfont zoom': 'iconfont zoom'}></i>
</SearchWrapper>
</Nav>
<Addition>
<Button className='writting'>
<i className="iconfont"></i>
寫文章
</Button>
<Button className='reg'>註冊</Button>
</Addition>
</HeaderWrapper>
)
}
}
const mapStateToProps=(state)=>{
return{
state:state.HeaderReducer
}
}
const mapDispatchToProps=(dispatch)=>{
return {
handleInputFocus()
{
return dispatch(action.searchFocus())
},
handleInputBlur()
{
return dispatch(action.searchBlur())
}
}
}
export default connect(state=>({state:state.HeaderReducer}),mapDispatchToProps)(App)