在不可变对象

时间:2016-11-28 14:33:31

标签: javascript immutable.js

这是一个简单的测试,我写过我想用不可变对象做什么

it('adds a new map with loaded data where the key is the ticker symbol', () => {
        const state = Map();
        const tickers = List.of('AAPL', 'TSLA', 'GOOGL');
        const nextState = addTickerKeys(state, tickers);

        expect(nextState).to.equal(fromJS({
            tickers: ['AAPL', 'TSLA', 'GOOGL'], 
            data: {
                AAPL: {}, 
                TSLA: {}, 
                GOOGL: {}
            }
        }));
    })

如何将数据对象和带有空数据的相应键添加到状态对象中?

这是我到目前为止所尝试的内容

export function addTickerKeys(state, tickers) {
    const newState = setTickers(state, tickers);
    const tickerList = newState.get('tickers');
    return tickerList.forEach((value, key, iter) => {
        return newState.setIn(['data', key]);
    })
}

我已经尝试使用value,key和iter代替返回newState.setIn(['data',key])替换文档(https://facebook.github.io/immutable-js/docs/#/Map/set

但是,我每次都会得到相同的回复,

  

AssertionError:预期3等于{Object(size,_root,...)}

有人可以向我解释出现了什么问题吗?这似乎是一个足够简单的任务,但我似乎正在努力使用Immutable对象,TypeScript中的文档没有帮助。

2 个答案:

答案 0 :(得分:1)

这是对此的快速回答,我刚想通了。

Immutable似乎没有一个很好的内置函数来执行此任务,并且你必须从纯函数返回状态的方式令人沮丧。

这是添加对象键值对的快速而肮脏的解决方案。

export function addTickerKeys(state) {
    const tickerArray = state.get('tickers');
    let newState = Map();
    for(let i = 0; i < tickerArray.size; i++){
        ctr++;
        newState = state.setIn(['data', tickerArray.get(i)], Map());
        state = state.concat(newState);
        if(i === tickerArray.size - 1){
            return state;
        }
    }
}

如果其他人仍然有不同的答案,可能会分享更优雅的内置解决方案。

答案 1 :(得分:1)

快速评论您的第一个解决方案:

forEach上的本地Array.prototype方法非常相似,不可变List类型上的forEach方法用于在List的每次迭代时执行一些副作用。但是,两者之间的一个细微差别是当回调函数在不可变forEach上返回false时,它将立即结束循环的执行,而本机forEach是无限的。在这里,您在列表中使用forEach方法,但返回一个值,表明您可能将它与不可变类型和数组上的map方法混淆。不幸的是,map也不是你想要的。

现在,另一个解决方案:

function addTickerKeys(state, tickers) {
  return tickers.reduce((acc, ticker) => {
    return acc.setIn([ 'data', ticker ], Map());
  }, Map({
    tickers: List(tickers),
  }))
}