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

[select] itemListRenderer #2252

Merged
merged 15 commits into from
Mar 20, 2018
Merged

[select] itemListRenderer #2252

merged 15 commits into from
Mar 20, 2018

Conversation

giladgray
Copy link
Contributor

@giladgray giladgray commented Mar 15, 2018

following up from @reiv's excellent work in #2080, this PR moves menuRenderer prop to QueryList and makes its behavior available to all select components. it also separate the renderer props from itemListRenderer props, such that iLR is the only one who knows about renderItem and the ref handler. renderer now receives the rendered itemList element, which simplifies its logic greatly.

  • 🔥 menuRendereritemListRenderer to match other prop names (tho this prop hasn't shipped yet, so not breaking)
  • 🌟 renderFilteredItems static function is generally useful for ...rendering filtered items.
  • pull initialContent, noResults, itemListRenderer up to QueryList props.
  • QueryList renderer receives rendered itemList ReactNode.
  • add filteredItems to renderer props (per Add filteredItems to queryList #2213).
  • itemListRenderer is now the only one with access to renderItem/items/itemsParentRef. the default itemListRenderer produces a Menu using filteredItems (to preserve arrow keys order).
  • delete repeated rendering code from components in favor of simply listProps.itemList

Gilad Gray added 6 commits March 15, 2018 14:24
add filteredItems to renderer props.
itemListRenderer is now the only one with access to renderItem/items/itemsParentRef.
the default itemListRenderer produces a Menu using filteredItems (to preserve arrow keys order).
@giladgray
Copy link
Contributor Author

@reiv, your input on this change would be greatly appreciated!

@blueprint-bot
Copy link

Merge branch 'develop' of github.com:palantir/blueprint into gg/item-list-renderer

Preview: documentation | landing | table

@blueprint-bot
Copy link

update docs

Preview: documentation | landing | table

Copy link
Contributor

@reiv reiv left a comment

Choose a reason for hiding this comment

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

👍 from me. Just have a few minor comments.

*
* The default implementation invokes `itemRenderer` for each item that passes the predicate
* and wraps them all in a `Menu` element. If the query is empty then `initialContent` is returned,
* and if all items are filtered away then `noResults` is returned.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: "if there are no items that match the predicate" (items could be empty, for all we know.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nice

* This is required for the `QueryList` to scroll the active item into view automatically.
*/
itemsParentRef: (ref: HTMLElement | null) => void;
/** Rendered elements returned from `menuRenderer` prop. */
Copy link
Contributor

Choose a reason for hiding this comment

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

menuRenderer -> itemListRenderer

@@ -231,6 +269,28 @@ export class QueryList<T> extends React.Component<IQueryListProps<T>, IQueryList
}
}

private defaultMenuRenderer = (listProps: IItemListRendererProps<T>) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would have suggested defaultItemListRenderer just for consistency, but that's a mouthful isn't it?


private renderItem = (item: T, index?: number) => {
const { activeItem, query } = this.props;
const matchesPredicate = this.state.filteredItems.indexOf(item) >= 0;
Copy link
Contributor

@reiv reiv Mar 16, 2018

Choose a reason for hiding this comment

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

I know this isn't new, but wouldn't it have been better in hindsight to cache the filtered items as an ES6 Set (or anything that's not O(N), really) to speed up this lookup?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, definitely a pain point in my head. we should do such a refactor.

* Helper method for rendering `props.filteredItems`, with optional support for `noResults`
* (when filtered items is empty) and `initialContent` (when query is empty).
*/
public static renderFilteredItems(
Copy link
Contributor

@reiv reiv Mar 16, 2018

Choose a reason for hiding this comment

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

Can we broaden the scope of this helper? How about instead of taking IItemListRendererProps, we take items: T[]; then an itemListRenderer can call it with either filteredItems or items, depending on which is more appropriate. Also, since this is meant to be called first and foremost by an itemListRenderer, it's a bit awkward that it's defined on QueryList, which we usually don't import directly when consuming Select and friends. Can we maybe make it a top-level export of the select package?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

cool yes def down for the root export.

taking the props as a first argument was a quick way to get off the ground, cuz it receives both items and renderItem in one go. the name indicates which set of items it'll use. my goal here was to streamline the 99% case; if you want to render items then you're on your own.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, fair enough on the streamlining part.

@blueprint-bot
Copy link

Merge branch 'develop' of github.com:palantir/blueprint into gg/item-list-renderer

Preview: documentation | landing | table

@blueprint-bot
Copy link

renderFilteredItems tests file

Preview: documentation | landing | table

Copy link
Contributor

@themadcreator themadcreator left a comment

Choose a reason for hiding this comment

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

Overall, I'm not super familiar with this feature, but this refactor seems pretty elegant.

@giladgray giladgray merged commit 6473f87 into develop Mar 20, 2018
@giladgray giladgray deleted the gg/item-list-renderer branch March 20, 2018 22:57
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.

4 participants