Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursive use #361

Closed
2 tasks done
bard opened this issue May 1, 2019 · 4 comments
Closed
2 tasks done

Recursive use #361

bard opened this issue May 1, 2019 · 4 comments
Labels

Comments

@bard
Copy link

bard commented May 1, 2019

馃悰 Bug Report

I've read through #100 and #225 but I'm still not sure whether what I'm looking for is supposed to work or not. So this may not be a bug report at all, just a request for clarification.

Given the following:

import produce from 'immer'

const reducer = (state, action) => produce(state, (draft) => {
    switch (action.type) {
        case 'INCREMENT':
            draft.counter++
            return
        case 'DOUBLE_THEN_INCREMENT':
            draft.counter *= 2;
            reducer(draft, { type: 'INCREMENT' })
            return
    }
})
const state = { counter: 2 }
const newState = reducer(state, { type: 'DOUBLE_THEN_INCREMENT' })
console.log(newState.counter)

I would expect the last line to print 5, instead it prints 4.

It's easy enough to work around it with a manual check to see if the passed state is already a draft, in which case I skip produce, like this:

const producer = (draft, action) => {
    switch (action.type) {
        case 'INCREMENT':
            draft.counter++
            return
        case 'DOUBLE_THEN_INCREMENT':
            draft.counter *= 2
            reducer(draft, { type: 'INCREMENT' })
            return
    }
}
const reducer = (stateOrDraft, action) => isDraft(stateOrDraft)
    ? producer(stateOrDraft, action)
    : produce(stateOrDraft, (draft) => producer(draft, action))

Link to repro

https://codesandbox.io/s/m506x7pwx8

Environment

  • Immer version: 3.1.1
  • Occurs with setUseProxies(true)
  • Occurs with setUseProxies(false) (ES5 only)
@bard bard added the bug label May 1, 2019
@bard
Copy link
Author

bard commented May 1, 2019

On second look, I see that I'm overloading the concept of reducer and a return-less call like:

            reducer(draft, { type: 'INCREMENT' })

Doesn't really make sense. Sorry for the noise, closing as wontmakesense.

@bard bard closed this as completed May 1, 2019
@aleclarson
Copy link
Member

Note: You can still do return reducer(draft, { ... }) and it should work

@bard
Copy link
Author

bard commented May 1, 2019

That is only if the draft is unmodified, no? In other words, just return reducer(draft, { ... }) would work, but draft.counter *= 2; return reducer(draft, { ... }) wouldn't.

@aleclarson
Copy link
Member

aleclarson commented May 1, 2019

@bard No, any draft that is passed into produce is wrapped with another draft that reflects any current changes.

edit: Oh, I forgot about the error that's thrown when a producer both modifies its draft and returns a new value. So yes, you're right about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants