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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor assigment of mapDispatch in connect.js #363

Closed
wants to merge 2 commits into from
Closed

Refactor assigment of mapDispatch in connect.js #363

wants to merge 2 commits into from

Conversation

seanstrom
Copy link

@seanstrom seanstrom commented Apr 21, 2016

Hey so a number of us from the ReactVegas meetup spent some time talking about the codebase. We specifically talked about the connect function and the small piece of code that was doing the assignment of mapDispatch. In the end we went over a few ways of refactoring the code and decided that it may serve us well to submit a PR.

Here's where that input got us:

  • The multiple assignments have been refactored to a single assignment and function call.
  • The new function handles returning a function or an object or defaultMapDispatchToProps.
  • The new function uses helpers from lodash to clean up type comparisons.
  • The new function uses a switch statement at the moment, this seem to read well and I can provide more context on that decision. A valid alternative would be to use guard statements instead. 😄

Overall we're excited to participate in the development of React-Redux, so any feedback is welcomed and appreciated. Thanks! 🎉

@seanstrom seanstrom changed the title Refactor assigning of mapDispatch in connect.js Refactor assigment of mapDispatch in connect.js Apr 21, 2016
@@ -3,6 +3,7 @@ import storeShape from '../utils/storeShape'
import shallowEqual from '../utils/shallowEqual'
import wrapActionCreators from '../utils/wrapActionCreators'
import warning from '../utils/warning'
import isFunction from 'lodash/isFunction'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s tiny but we already use typeof x === 'function' elsewhere, let’s keep doing it here as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 sounds good. The main reason I used isFunction was to make the code read similar to pattern matching. Like:

case value of
  Function -> value
  PlainObject -> wrapActionCreators(value)
  _ -> defaultMapDispatchToProps

If that's a style we're interested in then maybe we can talk about it more, but for this PR i'll change it to use the typeof expression.

@gaearon
Copy link
Contributor

gaearon commented Apr 21, 2016

Looks good, left one small nit.

@@ -19,6 +19,14 @@ function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

function getMapDispatch(value) {
switch (true) {
case (typeof value === 'function'): return value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very surprising use of switch statement. At this point I think the original version was clearer.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that a switch statement here can be unusual. But we can translate that directly to guard statements:

function getMapDispatch(value) {
  if (typeof value === 'function') {
    return value
  }

  if (isPlainObject(value)) {
    return wrapActionCreators(value)
  }

  return defaultMapDispatchToProps
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we can use if/else-if/else as well

function getMapDispatch(value) {
  if (typeof value === 'function') {
    return value
  } else if (isPlainObject(value)) {
    return wrapActionCreators(value)
  } else {
    return defaultMapDispatchToProps
  }
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main things I would promote are the function extraction, it adds some more clarity imo, and the revision to using isPlainObject as the second guard statement or else-if.

@gaearon
Copy link
Contributor

gaearon commented Apr 22, 2016

I’d like to leave it as is. I’m happy to take a more consistent refactoring that clears up some of the convoluted code we have right now. I think the convoluted code is inside the class, not outside it.

Adding something like getMapDispatch when we already have computeDispatchProps, finalMapDispatchToProps, configureFinalMapDispatch, mapDispatch, and mappedDispatch in the scope is only going to make it even more confusing. So I won’t take this, but I’m happy to consider a more comprehensive refactoring.

Thanks!

@gaearon gaearon closed this Apr 22, 2016
@seanstrom
Copy link
Author

No problem 😄! I'm happy to try a different refactor later.

@seanstrom seanstrom deleted the refactor-connect-if-else branch April 22, 2016 21:01
@amccloud
Copy link

amccloud commented Apr 26, 2016

@seanstrom I'm working on some of the code in the connect class. Would appreciate your feedback #368

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

Successfully merging this pull request may close these issues.

3 participants