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

關(guān)于redux中的reducer的兩點疑問

1、既然reducer強(qiáng)調(diào)不可變數(shù)據(jù)的概念為何不直接返回一個深拷貝之后的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
    }
    //或者運用性能更好的_.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
回答
編輯回答
夢囈

不知道我跟你想的一不一樣,可以看下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)鍵點在于每次reducer返回新的state會跟舊的state做===對比,如果false認(rèn)為store改變,從而觸發(fā)頁面重繪,如果true,則認(rèn)為不變,不會觸發(fā)重繪。所以reducer返回新的state是為了通知redux讓頁面重繪。

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

問題1: 每次深拷貝是可以的,但是會浪費性能,因為不管你做了任何操作都會創(chuàng)立一個新的對象,特別是內(nèi)容很多的對象,內(nèi)存占用負(fù)擔(dān)很大。
問題2:你說的沒錯,就是可以用Object. freeze來保證immutable,這也是很多輕量級的immutable庫內(nèi)部的實現(xiàn)方式,可以看 seamless-immutable,immutable-helper這類庫。

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

2017年5月4日 08:33