-
Notifications
You must be signed in to change notification settings - Fork 61
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
Add non-required debounceOptions prop object and forward it to lodash #94
Conversation
Whoops, I forgot to lint! I'll make a new PR squashed into one commit if you want. Thanks again! |
src/Component.js
Outdated
} = this.props; | ||
if ( | ||
debounceTimeout !== debounceTimeoutCurrent || | ||
debounceOptions !== debounceOptionsCurrent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comparing {} !== {}
would trigger updates on each render. Unfortunately for objects we need to use shallow object compare instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure when {} !== {}
is actually going to happen. The default is undefined
. If someone sets the property, the object will stay the same until they change it.
@@ -117,7 +130,7 @@ export class DebounceInput extends React.PureComponent { | |||
}; | |||
|
|||
|
|||
createNotifier = debounceTimeout => { | |||
createNotifier = (debounceTimeout, debounceOptions) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for a nit, but I usually do named arguments if there are more then one. Like ({debounceTimeout, debounceOptions})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are named arguments: (debounceTimeout, debounceOptions) =>
and this is destructuring named properties from the first argument: ({debounceTimeout, debounce}) =>
. If you change it to the latter, then every call to createNotifier
will have to create a new object (unless of course you have a single object instance that you keep around to pass to it) e.g. createNotifier({debounceTimeout: theTimeout, debounceOptions: theOptions})
(which of course could be shortened if the variables are named the same as the properties).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, right. Destructuring in JS is the only way of doing "named arguments" thing, which just does not exist in JS natively. Gives more clarity to the code that calls this sort of function.
Thanks! No need to squash, I actually like full history even if it is ridiculously big. |
Thanks for looking at this. If you want me to continue making changes just let me know. Otherwise I will leave things to you. I don't want to step on your toes if you have concerns which differ from mine. |
It's all good, the only concern is object comparison, and I'll happily merge the change! |
OK, I get what you're saying - you want to protect people who don't replace the entire |
I got it, I'll make that change and include it here - thanks. |
Not really for protection. It is more for code readability. with "positional" argsthis. createNotifier(first, second)
// ...
createNotifier = (debounceTimeout, debounceOptions) => {
// do things, all works
} with "named" (via destructuring) args:this. createNotifier({debounceTimeout: first, debounceOptions: second})
// ...
createNotifier = ({debounceTimeout, debounceOptions}) => {
// do things, all works
} Second example gives a little more idea of what those arguments to called function are by explicitly stating their names. PS: not much to do with this project, I just try to follow this convention in all the code I work on, so it is easier for other people to pick what is going on (myself in 1 year time falls into "other people" category pretty well too) |
So, I was wondering how you want to do the shallow object comparison? My vote is either for shallowequal or separate properties for each option and let There is react-addons-shallow-compare however the repo states that it is no longer maintained and it's legacy and to use Since you're using Lodash doesn't have a shallow object compare function, the author recommends to compose your own function with TBH, I didn't even think about this the first time because I swap the whole object every time (or use immutable.js which basically does that for me). |
Any extra runtime dep adds to the bundle size =( |
Regarding the named arguments via destructuring...if I make that change, then how do you want to change I would be tempted to do this: componentWillMount() {
this.createNotifier(this.props);
} Instead of doing the change I originally made: componentWillMount() {
const {
debounceTimeout,
debounceOptions
} = this.props;
this.createNotifier(debounceTimeout, debounceOptions);
} which kinda defeats the point of using named arguments to begin with. Would you rather see this? componentWillMount() {
const {
debounceTimeout,
debounceOptions
} = this.props;
this.createNotifier({debounceTimeout, debounceOptions});
} Thanks! |
OK, I'll roll back the last 2 commits and do a manual check. |
I think the last example would be the most explicit and clear. |
So, I am going to give up on this pull request because I don't like any of these changes. None of this is really my concern and this library is so simple that I could just pull it into my project. I don't like doing these extra comparisons because they get too awkward when you take into account that the object can be I also don't like going out of the way to use destructuring for named arguments because it causes new unnecessary objects to be created for each and every call to a function for very little benefit IMO. I don't do this in my own code. My solution to the lack of named arguments is to be consistent with variable names and use the same name everywhere. Sorry for wasting your time! Here was my simple attempt at writing a naive, pre-known object key comparison: function comp(debounceTimeout, debounceOptions, debounceTimeoutCurrent, debounceOptionsCurrent) {
if (
debounceTimeout !== debounceTimeoutCurrent || !(
// TODO: Make sure both objects aren't undefined/null here.
// Otherwise, do extra comparisons which makes this whole block ugly and awkward.
// Personally, I'm passing immutable props, so the simple comparison will work
// and my project won't use this. If I were making a library for others to use though,
// I'd probably just make a prop for each and let PureComponent do the work TBH.
debounceOptions.leading === debounceOptionsCurrent.leading &&
debounceOptions.trailing === debounceOptionsCurrent.trailing &&
debounceOptions.maxWait === debounceOptionsCurrent.maxWait
)
) { return 'changed'; } else { return 'equals'; }
} |
Also, I was writing and testing that |
No worries, thanks anyway! |
This PR is for #93 and it works very well for my own use case.
I tried my best to make changes with minimal impact. Tests were done manually with my own project, no test code or example was written.
Perhaps a separate property per option would be preferred, however I chose passing a single object so that there's only one extra strict comparison to make in
componentWillReceiveProps
and also because it's less work to pass the options directly todebounce()
, which already takes care of the case wheredebounceOptions
is undefined.Thanks! 🎉