如何使用immutable.js转换redux

时间:2016-09-28 10:05:18

标签: reactjs redux immutable.js

我想尝试练习如何使用immutable.js
但我不知道如何编辑我的减速机到不可变的方式。 (我试着在github上找到一些代码,但它们是基本的)
我的组件也有错误 所以我想请求帮助,告诉我如何重构我的减速机?

这是我原来的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_STATE

添加换行fromJS()

** immutable 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 (...)
});

2 个答案:

答案 0 :(得分: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 :(得分:0)

你不能用点表示法引用object属性,因为它是一个Immutablejs Map(当你将状态对象传递给fromJS Immutablejs函数时,你在reducer中创建了Map)来使用你需要使用的Map上的函数map Immutablejs api返回一个新框而不是对旧框的引用。

首先使用getIn函数,该函数将返回一个新框而不是对旧框的引用。

根据你通过道具传递状态的方式,我无法给你一个明确的答案,我很困惑editZone属性的来源,因为我只能在你的初始状态下看到它只是一个函数名,是吗?切片状态并从函数名称创建属性?但无论如何你可以尝试一下

变化:

const boxes = this.props.editZone.box; const playgroundObjetcs = boxes.map(box =&gt; {return(...)});

要:

const playgroundObjects = this.props.getIn(['editZone','box'])。map(box =&gt; {return(...)});

或者尝试:

const boxes = this.props.editZone.box.toJS() playgroundObjetcs = boxes.map(box =&gt; {return(...)});

希望现在对于发生的事情有意义。