Immer: Default returned value.

Created on 4 May 2018  路  8Comments  路  Source: immerjs/immer

It's a bit strange for me:

console.log(produce(null, draft => draft)); //null
console.log(produce(null, draft => {})); //undefined

bug

Most helpful comment

In redux it's a common pattern to pass null as default state value. And redux expects, that undefined will not be returned from reducer.

Given example in readme confuses in case when state is null

import produce from "immer"

const byId = (state = null, action) =>
    produce(state, draft => {
        switch (action.type) {
            case RECEIVE_PRODUCTS:
                action.products.forEach(product => {
                    draft[product.id] = product
                })
        }
    })
// if we omit default case, then undefined will be returned instead of null

Also there is a test which says exactly what it should do:

        it("should return the original without modifications", () => {
            const nextState = produce(baseState, () => {})
            expect(nextState).toBe(baseState)
        })

All 8 comments

Hi @MaxBoltik,

The behavior is as expected, see explanation below:

1) console.log(produce(null, draft => draft)); //null

Since the given reducer draft => draft does not have a function body, the arrow function will implicitly return the expression on the "right side" of the reducer.
So in this case, the currentState null is passed to the producer, and then null is returned from the producer, resulting in the nextState null.

2) console.log(produce(null, draft => {})); //undefined

The given reducer draft => {} does have an empty function body, so the function will always return undefined, because JavaScript functions without a return statement always return undefined.
Therefore the nextState will always be undefined.

Hi @pkerschbaum, maybe you are right. But in the readme.md i see the next:

Notice that it is not needed to handle the default case, a producer that doesn't do anything will simply return the original state.

In the given example, produce will return undefined if "action.type" is different from RECEIVE_PRODUCTS.

In redux it's a common pattern to pass null as default state value. And redux expects, that undefined will not be returned from reducer.

Given example in readme confuses in case when state is null

import produce from "immer"

const byId = (state = null, action) =>
    produce(state, draft => {
        switch (action.type) {
            case RECEIVE_PRODUCTS:
                action.products.forEach(product => {
                    draft[product.id] = product
                })
        }
    })
// if we omit default case, then undefined will be returned instead of null

Also there is a test which says exactly what it should do:

        it("should return the original without modifications", () => {
            const nextState = produce(baseState, () => {})
            expect(nextState).toBe(baseState)
        })

Oh I see, my mistake

Maybe you can fix that?

@MaxBoltik could you open a PR with a unit test to reproduce the issue? This looks like a bug indeed.

Added a spec and fix in #157

Released as 1.3.1, thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jameskfry picture jameskfry  路  3Comments

vidarc picture vidarc  路  3Comments

DanielRuf picture DanielRuf  路  5Comments

dfadev picture dfadev  路  6Comments

Knacktus picture Knacktus  路  5Comments