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

[Labs] Propagate event correctly when handling empty list #1256

Merged
merged 1 commit into from
Jun 21, 2017
Merged

[Labs] Propagate event correctly when handling empty list #1256

merged 1 commit into from
Jun 21, 2017

Conversation

k-simons
Copy link
Contributor

@k-simons k-simons commented Jun 20, 2017

Fixes #0000

Checklist

Changes proposed in this pull request:

Right now if you have a class that instantiates a raw queryList and passes in an empty filtered list and undefined as the active state, then on componentDidUpdate it will call update and pass an active item of undefined. If you have a parent class that listens to onActiveItemChange and then sets its state, the parent class will be re-rendered. Then the queryList will will be re-rendered, and so on and so forth. This will cause an infinite re-rendering loop and a stackover-flow error. You can emulate this behavior if you remove @pure-render from select.tsx and remove:

        if (filteredItems.length === 0) {
            return noResults;
        }

so the query list is always rendered.

Then if you filter to an empty list in select.tsx, you will get a stack-overflow error

Reviewers should focus on:

Screenshot

@giladgray This fixes an edge case of propagating an incorrect change event

@tgreenwatts
Copy link
Contributor

tgreenwatts commented Jun 20, 2017

Gilad is out of town but @gscshoyru will take a look. Thanks for the contribution!

@gscshoyru
Copy link
Contributor

@k-simons what exactly is the edge case here? What was the bad behavior, before?

private handlingEmptyListCorrectly() {
const emptyFilteredList = this.state.filteredItems.length === 0;
const activeItemIsUndefined = this.props.activeItem === undefined;
return emptyFilteredList && activeItemIsUndefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this honestly might make more sense to inline, above, since it's just in one place, and the function name is not particularly helpful. Plus the logic is harder to follow like this, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gscshoyru inline into componentDidUpdate ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, in the if statement condition. The fact that I have to demorgan's law on this in my head while going back and forth between two lines makes this somewhat difficult to parse.

@llorca
Copy link
Contributor

llorca commented Jun 20, 2017

@k-simons Can you please fill up the description and provide details about the edge case you hit, before/after behaviors, etc? Thanks!

@llorca llorca changed the title Do not propogate event if correctly handling empty list [Labs] Do not propogate event if correctly handling empty list Jun 20, 2017
@k-simons
Copy link
Contributor Author

@gscshoyru @llorca apologies, gilad and I had talked about this a little Friday. Updated with context

@llorca llorca changed the title [Labs] Do not propogate event if correctly handling empty list [Labs] Propagate event correctly when handling empty list Jun 20, 2017
@k-simons
Copy link
Contributor Author

@gscshoyru fixed

@@ -186,7 +186,7 @@ export class QueryList<T> extends React.Component<IQueryListProps<T>, IQueryList
this.shouldCheckActiveItemInViewport = false;
}
// reset active item (in the same step) if it's no longer valid
if (this.getActiveIndex() < 0) {
if (this.getActiveIndex() < 0 && (this.state.filteredItems.length !== 0 || this.props.activeItem !== undefined)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Much easier to understand.

It might be prudent to add a bit more to the above comment explaining what this is doing (essentially, don't fire the event if there's nothing to pick and the active item is already undefined) but it's probably fine either way.

@k-simons
Copy link
Contributor Author

@gscshoyru updated comment. Should be good to merge

@k-simons
Copy link
Contributor Author

fixed lint 🙃

Copy link
Contributor

@cmslewis cmslewis left a comment

Choose a reason for hiding this comment

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

Thanks, @k-simons. Left one question. Also, can you add a unit test to verify this?

if (this.getActiveIndex() < 0) {
// Also don't fire the event if the active item is already undefined and there is nothing to pick
if (this.getActiveIndex() < 0 &&
(this.state.filteredItems.length !== 0 || this.props.activeItem !== undefined)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we expand this check to account for null values too? (i.e. this.props.activeItem != null)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cmslewis sure will work on a unit test. I don't think we should add null. Mostly because if this.state.filteredItems is empty, then this.state.filteredItems[0] is undefined. In that case there actually is a difference to props.selectedItem and the event (null vs undefined)

@k-simons
Copy link
Contributor Author

@cmslewis tests added

@cmslewis cmslewis merged commit aa6e690 into palantir:master Jun 21, 2017
@cmslewis
Copy link
Contributor

Thanks, @k-simons!

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.

None yet

5 participants