鍍金池/ 問(wèn)答/PHP  HTML/ 關(guān)于redux中的reducer的兩點(diǎn)疑問(wèn)

關(guān)于redux中的reducer的兩點(diǎn)疑問(wèn)

1、既然reducer強(qiáng)調(diào)不可變數(shù)據(jù)的概念為何不直接返回一個(gè)深拷貝之后的state,例如_.cloneDeep
2、既然不能直接更改state,為何不利用Object.freeze,或者類似的方法讓state不可改變

import { SET_BOOKS, ADD_BOOK, REMOVE_BOOK, CHANGE_BOOK_PRICE } from '../actions/book.js'

const initBooks = []

const books = (state, action) => {
    if (state === undefined) {
        state = initBooks
    }
    //或者運(yùn)用性能更好的_.cloneDeep
    let tmpBooks = JSON.parse(JSON.stringify(state))
    switch (action.type) {
        case SET_BOOKS:
            return action.books
            break
        case ADD_BOOK:
            // return [...state,action.newBook]
            tmpBooks.push(action.newBook)
            return tmpBooks
            break
        case REMOVE_BOOK:
            return state.filter(item => {
                return item.id !== action.bookId
            })
            break
        case CHANGE_BOOK_PRICE:
            tmpBooks.forEach(item => {
                if(item.id===action.bookId){
                    item.price=action.newPrice
                }
            });
            return action.books
            break
        default:
            return state
    }
}

export default books
回答
編輯回答
夢(mèng)囈

不知道我跟你想的一不一樣,可以看下combineReducers的源碼:

var hasChanged = false
    var nextState = {}
    for (var i = 0; i < finalReducerKeys.length; i++) {
      var key = finalReducerKeys[i]
      var reducer = finalReducers[key]
      var previousStateForKey = state[key]
      var nextStateForKey = reducer(previousStateForKey, action)
      if (typeof nextStateForKey === 'undefined') {
        var errorMessage = getUndefinedStateErrorMessage(key, action)
        throw new Error(errorMessage)
      }
      nextState[key] = nextStateForKey
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    return hasChanged ? nextState : state

關(guān)鍵點(diǎn)在于每次reducer返回新的state會(huì)跟舊的state做===對(duì)比,如果false認(rèn)為store改變,從而觸發(fā)頁(yè)面重繪,如果true,則認(rèn)為不變,不會(huì)觸發(fā)重繪。所以reducer返回新的state是為了通知redux讓頁(yè)面重繪。

2017年9月6日 16:42
編輯回答
朽鹿

問(wèn)題1: 每次深拷貝是可以的,但是會(huì)浪費(fèi)性能,因?yàn)椴还苣阕隽巳魏尾僮鞫紩?huì)創(chuàng)立一個(gè)新的對(duì)象,特別是內(nèi)容很多的對(duì)象,內(nèi)存占用負(fù)擔(dān)很大。
問(wèn)題2:你說(shuō)的沒(méi)錯(cuò),就是可以用Object. freeze來(lái)保證immutable,這也是很多輕量級(jí)的immutable庫(kù)內(nèi)部的實(shí)現(xiàn)方式,可以看 seamless-immutable,immutable-helper這類庫(kù)。

題外話,immutable 保證了 reducer 在內(nèi)部數(shù)據(jù)變化后,返回一個(gè)新對(duì)象,用處是判斷兩次數(shù)據(jù)時(shí),只需要進(jìn)行一次 reference 判斷,而不用 deepEqual 判斷,從而節(jié)省性能開(kāi)銷。

2017年5月4日 08:33