blueprint
blueprint copied to clipboard
Suggest onQueryChange appears to fire twice because callback changes items prop
Environment
- Package version(s): core 3.6.1 / select 3.2.0 / react 16.5.2
- Browser and OS versions: mac, chrome latest
Steps to reproduce
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
};
Actual behavior
the query()
function is called twice for every keystroke, likely because the result of that call changes items
Expected behavior
it should only be called once even though items
changes.
Possible solution
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.
The problem still exists