2016-09-28 73 views
0

我想嘗試練習如何使用immutable.js
但我不知道如何編輯我的reducer以不可變的方式。 (我嘗試在github上找到一些代碼,但它們很基本)
而且我的組件也有錯誤。
所以我想要求幫忙來指導我如何重構我的reducer?如何轉換redux與immutable.js

這是我原來的reducer.js

原reducer.js

import * as TYPE from '../constants/ActionTypes'; 

const INIT_STATE = { 
    box: [ 
    { 'id': 1, 
     'axisX': 10, 
     'axisY': 10, 
     'width': 200, 
     'height': 200, 
    }, 
    { 'id': 2, 
     'axisX': 20, 
     'axisY': 300, 
     'width': 200, 
     'height': 200, 
    } 
    ] 
}; 


export default function editZone(state = INIT_STATE, action) { 
    let newState = null; 
    switch (action.type) { 
    case TYPE.UPDATE_POSITION: 
     newState = Object.assign({}, state); 
     newState.box = newState.box.map(box => { 
     if (box.id === action.payload.id) { 
      box.axisX = action.payload.x; 
      box.axisY = action.payload.y; 
     } 
     return box; 
     }); 
     return newState; 
    default: 
     return state; 
    } 
} 

我編輯使用immutable.js,我只需要添加包裹INIT_STATEfromJS()

**不變reducer.js **

import {List, Map, fromJS} from 'immutable'; 

const INIT_STATE = fromJS({ 
     box: [ 
     { 'id': 1, 
      'axisX': 10, 
      'axisY': 10, 
      'width': 200, 
      'height': 200, 
     }, 
     { 'id': 2, 
      'axisX': 20, 
      'axisY': 300, 
      'width': 200, 
      'height': 200, 
     } 
     ] 
    }); 

我面臨着一個錯誤:TypeError: Cannot read property 'map' of undefined
我盡力勸慰輸出this.props.editZone
它顯示Map {size: 2, _root: ArrayMapNode, __ownerID: undefined, __hash: undefined, __altered: false}
我怎樣才能解決這個問題?

boxComponent.js

const boxes = this.props.editZone.box; 
const playgroundObjetcs = boxes.map(box => { 
    return (...) 
}); 
+0

首先在reducer裏面使用state.get('box')來獲得狀態的box屬性,然後你可以在該數組上使用map。 –

回答

0

我在我的代碼使用Immutable.js。

希望這可能會幫助你。

減速

import Immutable from 'immutable'; 
import actionConsts from 'constants/actions'; 

const initialState = Immutable.fromJS({ 
    isUserLoggedIn: false 
}); 

const user = (state = initialState, action = {}) => { 
    switch (action.type) { 
     case actionConsts.get('RECEIVE_INIT_DATA'): 
      return state.merge(Immutable.fromJS(action.payload.user)); 
     default: 
      return state; 
    } 
}; 

export default user; 

集裝箱

import React, { PropTypes } from 'react'; 
import { connect } from 'react-redux'; 
import Base from 'components/base'; 
import 'styles/app.sass'; 
import { fetchAppBaseData } from 'actions/init'; 
import { clearErrorAction } from 'actions/error'; 

class BaseContainer extends React.Component { 

    render() { 
     return (
      <Base {...this.props} /> 
     ); 
    } 
} 

BaseContainer.propTypes = { 
    skin: PropTypes.object.isRequired, 
    sim: PropTypes.object.isRequired, 
    user: PropTypes.object.isRequired, 
    children: PropTypes.object.isRequired, 
    fetchAppBase: PropTypes.func.isRequired, 
    clearError: PropTypes.func.isRequired 
}; 
BaseContainer.defaultProps = { 
    skin: {}, 
    user: {}, 
    sim: {} 
}; 

const mapStateToProps = (state) => ({ ...(state.toJS()) }); 

const mapDispatchToProps = (dispatch) => ({ 
    fetchAppBase() { 
     dispatch(fetchAppBaseData()); 
    }, 

    clearError() { 
     dispatch(clearErrorAction()); 
    } 
}); 

export default connect(mapStateToProps, mapDispatchToProps)(BaseContainer); 
+1

這是一個怎樣的答案? – Aaron

0

你不能用點引用的對象屬性不因爲它是一個Immutablejs Map(當你將狀態對象傳遞給fromJS Immutablejs函數時,你在Reducer中創建了Map)使用該Map上的函數映射,所以需要使用Immutablejs api返回一個新的框而不是參考舊盒子。

首先使用getIn函數,它將返回一個新的盒子而不是對舊盒子的引用。

根據你通過道具傳遞狀態的方式,我不能給你一個明確的答案,我很困惑editZone屬性來自哪裏,因爲我無法在初始狀態下將它看作函數名稱,你切分你的狀態並從函數名稱創建屬性?但無論如何,你可以嘗試沿着線的東西

變化:

常量盒= this.props.editZone.box; const playgroundObjetcs = boxes.map(box => {return(...)}); 。

到:

常量playgroundObjects = this.props.getIn([ 'editZone', '盒'])映射(框=> {返回(...)});

可選擇地嘗試:

常量盒= this.props.editZone.box.toJS() playgroundObjetcs = boxes.map(框=> {返回(...)});

希望這會對現在發生的事情有意義。