Skip to content
This repository was archived by the owner on Sep 10, 2022. It is now read-only.

Adding an optional callback argument to the dispatch method provided by withReducer#595

Merged
wuct merged 1 commit intoacdlite:masterfrom
therealparmesh:with_reducer_dispatch_callback
Mar 7, 2018
Merged

Adding an optional callback argument to the dispatch method provided by withReducer#595
wuct merged 1 commit intoacdlite:masterfrom
therealparmesh:with_reducer_dispatch_callback

Conversation

@therealparmesh
Copy link
Copy Markdown
Contributor

@therealparmesh therealparmesh commented Jan 24, 2018

I thought of this after looking at withState, which provides stateUpdater methods that can take in callbacks. My rationale for allowing for an optional callback that receives the new state for the dispatch method that withReducer provides is that after calculating the new state, you might want to propagate state changes elsewhere. Maybe you need to call a given onChange prop or handle some other side effect like that.

We could just execute the reducer with the old state and the action to generate the new state outside of the dispatch call, but I find it really clunky to calculate the new state twice - once implicitly as a result of the dispatch call and once explicitly by executing the reducer - in order to address these types of scenarios. I am also not a fan of programmatically detecting state changes and handling the associated side effects via lifecycle methods.

I chose to use a plain callback over a promise solely because I did not see recompose making any real use of promises and I did not want to introduce a new paradigm. I am not attached to this decision.

Thank you for this amazing library! Please let me know what you think of this idea.

@codecov-io
Copy link
Copy Markdown

codecov-io commented Jan 24, 2018

Codecov Report

Merging #595 into master will increase coverage by 0.09%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #595      +/-   ##
==========================================
+ Coverage   88.18%   88.28%   +0.09%     
==========================================
  Files          49       49              
  Lines         364      367       +3     
==========================================
+ Hits          321      324       +3     
  Misses         43       43
Impacted Files Coverage Δ
src/packages/recompose/withReducer.js 92.85% <100%> (+1.94%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update de05776...6e92f41. Read the comment docs.

@istarkov
Copy link
Copy Markdown
Contributor

Hi, Thank you.
It was created as some kind of simplified redux, no callback there https://redux.js.org/docs/api/Store.html#dispatch
We have no analog of middlewares to call side effects on action complete etc.
I personally dont like the idea to provide api extension the only use case it has is to call some side-effect and somehow broke similarity to redux dispatch. In all such cases you can call sideeffect in handler with just action (and compute state where it needed using the same logic as in store)

@therealparmesh
Copy link
Copy Markdown
Contributor Author

therealparmesh commented Jan 24, 2018

Thank you for the feedback!

While I definitely see that withReducer is a simple redux analogue, I still think that something that models this functionality of dispatch could really benefit recompose.

The store's reducing function will be called with the current getState() result and the given action synchronously. Its return value will be considered the next state. It will be returned from getState() from now on, and the change listeners will immediately be notified.

@istarkov
Copy link
Copy Markdown
Contributor

I havent used withReducer ;-) @wuct what are you think about, may be in absence of middlewares this is not so bad as I wrote?

@therealparmesh
Copy link
Copy Markdown
Contributor Author

therealparmesh commented Jan 24, 2018

It'd be great to have middlewares like in redux to manage side effects cleanly. 😄 But I imagine that adding support for middleware would be tough, given that the withReducer HOC is basically emulating the redux store with the main difference being that the HOC is bound to React's API internally.

There are already some differences in the dispatch implementations because of this. The dispatch from withReducer is technically asynchronous since it relies on and returns a setState call internally. So, it does not return the same thing as dispatch from redux as is.

So I ask - in lieu of middleware support and given that the dispatch implementations are seemingly going to be slightly different - whether or not an API extension like this is an acceptable way to handle this simple side effect type of logic with the withReducer HOC.

@azz0r
Copy link
Copy Markdown

azz0r commented Feb 7, 2018

My suggestion would be to pass in a callback to the payload, e.g.

https://github.com/azz0r/fedsimulator/blob/ppvs/src/actions/data.js#L9
https://github.com/azz0r/fedsimulator/blob/ppvs/src/reducers/roster.js#L24

But I believe this is considered bad practise, you'd be expected to use componentWillReceiveProps to check the nextProps change then trigger your "callback".

@wuct
Copy link
Copy Markdown
Contributor

wuct commented Feb 11, 2018

@therealparmesh @istarkov I don't like the idea to extend API surface for side effects, too. However, as @therealparmesh said, we've already provided this kind of surface in withState, and if we consider withReducer as another setState wrapper, it makes sense that we create the same surface for it. Moreover, I don't think we will support for middlewares, so it's okay for me to have this callback.

@azz0r IMHO it's not a good idea because impure reducers are harder to test and trace code.

@therealparmesh
Copy link
Copy Markdown
Contributor Author

@wuct @istarkov Great! Thank you for taking the time to look at this. What should the next steps be?

@wuct
Copy link
Copy Markdown
Contributor

wuct commented Feb 24, 2018

Looks like it is good to be shipped. @istarkov any thought?

@tlginn
Copy link
Copy Markdown

tlginn commented Mar 6, 2018

Any update on if/when this will be released? It would be helpful in a project where I'm currently using recompose.

There are workarounds for sure, but I'm not a fan of having an impure reducer either and componentWillReceiveProps is distant from the code that is dispatching the action. Having this would be a great convenience.

@istarkov
Copy link
Copy Markdown
Contributor

istarkov commented Mar 6, 2018

Oops sorry,
@wuct I see nothing bad, please merge.

@wuct wuct merged commit 6b63cde into acdlite:master Mar 7, 2018
@wuct
Copy link
Copy Markdown
Contributor

wuct commented Mar 7, 2018

Thank you @therealparmesh

@therealparmesh therealparmesh deleted the with_reducer_dispatch_callback branch September 7, 2019 03:55
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants