the following is a very simple component that uses Suggest to display a list of users returned by a REST endpoint. searchUsersByName makes a simple fetch() as you'd expect.
export class UserNameLookup extends Component {
state = { results: [] };
query = async query => {
const final = query ? query.trim() : "";
const results = final ? await searchUsersByName(final) : [];
this.setState({ results });
};
itemRenderer = ({ first, last, uuid }, { handleClick }) => (
<MenuItem
className={ITEM_CLASS}
key={uuid}
text={`${first} ${last}`}
onClick={handleClick}
/>
);
inputValueRenderer = ({ first, last }) => first + " " + last;
itemSelect = item => {
if (this.props.onSelect) {
this.props.onSelect(item);
}
};
render() {
return (
<div className={"user-name-lookup"}>
<Suggest
items={this.state.results}
noResults={
<MenuItem
className={ITEM_CLASS}
disabled={true}
text={"No results."}
/>
}
onQueryChange={this.query}
itemRenderer={this.itemRenderer}
inputValueRenderer={this.inputValueRenderer}
onItemSelect={this.itemSelect}
inputProps={searchProps}
/>
</div>
);
}
}
UserNameLookup.propTypes = {
onSelect: PropTypes.func
};
the query() function is called twice for every keystroke, likely because the result of that call changes items
it should only be called once even though items changes.
im not sure how to make this work the "ergonomic" way, but obviously i tried to keep track of the query string on my own in the callback in order to avoid firing twice, but that seems impossible because this line https://github.com/palantir/blueprint/blob/develop/packages/select/src/components/query-list/queryList.tsx#L183 in setQuery() calls the callback BEFORE setting the internal state
im not sure how im supposed to do an async call in this situation.
EDIT: also just to be clear, the component works perfectly fine. i only realized it was making two calls when looking at the network tab in dev tools.
I've ran into same issue with Select
i only realized it was making two calls when looking at the network tab in dev tools.
@ixtli You can use lodash/debounce function to prevent multiple requests on one keystroke
Same here the component fires 2 times instead of 1.
I also think that onQueryChange break the custom inputProps = {{ onChange : fn() }} but i can't find anywhere in docs a mention so maybe it's only in my case.
if you just want to avoid double call you can check if event is not undefined :
onQueryChange = (query, event) => {
if (event) {
console.log('should send only once')
}
}
Look like onActiveItemChange fired also two times for the same reason
We are having the same problem with Suggest, using onQueryChange method gets fired twice per keystroke. We found the problem is related with the way the component behaves in what is supposed to be a controlled input.
By doing
<Suggest
query='',
onQueryChange={(t, e) => { console.log(t, e); }}
{...otherProps}
>
In here, the input should never be changed. because we are effectively settings its value to a constant.
This is broken, so not exactly a controlled input.
Most helpful comment
Same here the component fires 2 times instead of 1.
I also think that onQueryChange break the custom
inputProps = {{ onChange : fn() }}but i can't find anywhere in docs a mention so maybe it's only in my case.if you just want to avoid double call you can check if event is not undefined :