0

With regards to this question:

useReducer Action dispatched twice

I've adapted a small code snippet in codesandbox taken from Dan Abramov's blog right here.

Now my question is this:

If I type something in the input field in between the 5 seconds interval and then inspect the console output I observe that when dispatch fires the "supposedly" closed over value of step is the newly updated value I just typed in the input field instead of 1 which was the case when useEffect was declared. Why is this the case?

stratis
  • 7,750
  • 13
  • 53
  • 94

1 Answers1

1

Every time you change the value of your input you call setStep which triggers a re-render of your Counter component. This in turn leads to your reducer function being re-created with the updated value of step being closed over.

Your effect does not close over the initial value of step, just over dispatch.

To observe the behaviour you expect you would have to wrap your reducer in a useCallback without providing any dependencies. Then it wouldn't get recreated every time.

trixn
  • 15,761
  • 2
  • 38
  • 55
  • Right... but dispatch closes over the initial reducer which in turn closes over step. Unless.. dispatch is itself "recreated" on every render (to reference each new reducer) but at the same time "stays the same"... I'm so buffled... – stratis Sep 02 '19 at 19:13
  • @kstratis Except that `dispatch` does not close over the reducer. Dispatch is just a function that, when called with an action, calls whatever is currently the reducer. And your reducer changes with every render of `Counter`. `dispatch` itself does not change between renders though. – trixn Sep 03 '19 at 08:37
  • right... but the reference to the reducer does change which shouldn’t be possible since the entire render is basically a closure... – stratis Sep 03 '19 at 08:49
  • @kstratis How do you conclude that this couldn't be possible? This is exactly, what you can do with `useRef`. It may even be implemented like that. – trixn Sep 03 '19 at 08:50
  • Basically because of this: https://overreacted.io/a-complete-guide-to-useeffect/#each-render-has-its-own-everything. However a closure (render in this case) may still hold a reference to a variable/pointer from the outer scope which seems to be the case after all... – stratis Sep 03 '19 at 09:28