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
On First Focus, Suggestions Don't Render if a Value is Present #126
Comments
It's because the
|
Unfortunately, adding this doesn't fix the issue. The basic flow is this:
Here is the general idea for my code: export default class AutosuggestComponent extends React.Component{
constructor(props) {
super(props)
this.bind()
this.state = {
value: this.props.value || "",
placeholder: this.props.placeholder || "",
suggestions: this.getSuggestions()
}
this.possibilities = this.props.possibilities || []
this.search = this.props.searchFunction || (() => {return []})
this.externalOnChange = this.props.onChange || (() => {return})
}
getSuggestions(value = "") {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
console.log("get")
return (inputLength === 0 ? [] : this.possibilities.filter(possibility =>
possibility.value.toLowerCase().slice(0, inputLength) === inputValue))
}
...
componentWillReceiveProps(nextProps) {
console.log("will receive props")
this.possibilities = nextProps.possibilities || []
console.log(nextProps)
/*const suggestions = this.getSuggestions(nextProps.value)
this.setState({
suggestions: suggestions
})*/
}
componentWillMount() {
console.log("will mount")
this.search()
}
componentDidMount() {
console.log("did mount")
this.setState({
suggestions: this.getSuggestions(this.state.value)
})
}
render() {
console.log("render")
const {value, placeholder, suggestions} = this.state
const inputProps = {
value,
placeholder,
onFocus: this.onFocus,
onChange: this.onChange
}
return (<Autosuggest id={value}
suggestions={suggestions}
getSuggestionValue={this.getSuggestionValue}
shouldRenderSuggestions={this.shouldRenderSuggestions}
renderSuggestion={this.renderSuggestion}
inputProps={inputProps}
onSuggestionsUpdateRequested={this.onSuggestionsUpdateRequested}
/>)
}
} |
I edited the Basic Codepen to show the implementation in action: http://codepen.io/anon/pen/rxgjZx. My changes were: this.state = {
value: 'C',
suggestions: getSuggestions('C')
}; The important thing is to make sure that the |
Ah, see that still won't work because the possible suggestions aren't available at that time; the constructor is called before the componentWillMount method is called. Doing that in my code returns an empty array. so no suggestions are displayed. If there was some way to force the AC component to show results when the component has focus, that might do it for me, but I don't know how to make that happen. |
Oh it's not necessary to have the suggestions loaded in If you have, then I would suggest placing a breakpoint in |
No unfortunately that's not it either - I did overwrite that one :( So in the basic codepen example, languages is pre-populated with languages to choose from. In my example, imagine languages starts empty, but gets filled in when the search function is called on the database. It gets filled in after the constructor fires, when componentWillMount then fires (and incidentally, when onFocus fires as well, to get updates). So onSuggestionsUpdateRequested is never called until an edit occurs. Unfortunately, I can't update the suggestions in componentWillMount because that gets called every single time you change anything in the field, including keying over a suggestion. |
Could your problem be that in your |
No, sadly that's not it either. The deconstruction of state works as expected in render, the problem is at that point, this.state.suggestions has an empty array. |
Sorry missed that. So all that remains is to get your |
I did take a look at that, and while that would be a good place to get the update for suggestions, the problem is that the possibilities are returned via a component higher up the React chain, so a re-render is called when the search is performed, and the suggestions wouldn't get properly calculated at that point. Basically, I need to get the new suggestions and display them AFTER the AC component render is triggered from the search. |
If suggestions are being populated from a higher component, you can have them bound to state in the higher component and then pass them into the Autocomplete component via props. That way when the async call finishes, it will trigger a re-render of the Autocomplete component with the updated suggestions. |
Close, but the suggestions are being calculated locally in the AC component; it's the POSSIBILITIES that are being computed in a higher component. So this is like the language possibilities in the BASIC example, except instead of being static, they are being populated dynamically from a HUGE DB via the search within the AC component. The reason the possibilities need to be updated dynamically is because of the cost of the API call on the DB, and avoiding the search returning the entire DB. So it's not an issue of computing the suggestions when the AC components are first created, but the fact that the possibilities aren't available until the AC component is first constructed, but after the first edit they are. |
I think I'm starting to understand a bit better, thanks for bearing with me. So to clarify, your problem is that your total data set I see in the above example that you've commented out code in |
Cool, glad we're getting on the same page :) So yes, your summary is correct: the total data set possibilities is updated when the higher component returns the result of the async call, but suggestions isn't updated until the input is changed. The code in willReceiveProps is commented out because if I update the suggestions as soon as I get back the possibilities, the AC component behaves undesirably. Because the suggestions get updated whenever the current value in state changes (which occurs when keying over them), the suggestion list changes immediately, which is undesirable. For example, you have 5 suggestions: Company_A, Company_B, Company_AA, and Company_AAA. If you key over Company_A, the suggestions immediately get pared down to Company_A, Company_AA, and Company_AAA, which is undesirable if you are trying to key down to Company_B. I'm thinking I might get around this by telling state not to update on key up or down (instead performing more like mouse hovering). |
react-autosuggest already handles the behavior when cycling through suggestions with the arrow keys, so I think it's best to leave the heavy lifting to that. Instead, in |
Okay, so I finally got it working the way I want to, and here's how: onSuggestionsUpdateRequested({ value }) {
this.setState({
suggestions: this.getSuggestions(value)
})
this.search()
}
onSuggestionSelected(event, { suggestion, suggestionValue, method }) {
this.setState({
value: suggestion.value
})
this.externalOnChange(event, {newValue: suggestion.value})
}
onChange(event, {newValue, method}) {
if (method !== "up" && method !== "down") {
this.setState({
value: newValue
})
this.externalOnChange(event, {newValue})
}
}
componentWillReceiveProps(nextProps) {
this.possibilities = nextProps.possibilities || []
const suggestions = this.getSuggestions(this.state.value)
this.setState({
suggestions: suggestions
})
}
componentWillMount() {
this.search()
} While I realize that AC is handling the cycling of suggestions when using the arrow keys, it had the undesirable (at least in my case) effect of updating the field's value (as I outlined in the example I gave above). Thanks for all of your input and effort; I appreciate it! Now the suggestions are populated immediately, and the field acts as desired :) |
good work figuring it out! |
I'm running into an issue where an Autosuggest field is not rendering suggestions on first focus if the field is initially rendered with a value. For instance, if you change the 'Basic' Codepen example to initialize state with a value of "C", no suggestion will be rendered when the field first gains focus (when it should give the suggestions "C, C++, C#, and Clojure). Editing the field kicks the suggestions into gear, and they begin appearing after that without issue.
I'm building a form that at times might have some fields initialized with values that are partial matches for suggestions, and would like to see the suggestions show up on first focus.
Is this a bug, or am I doing something wrong? Thank you in advance!
The text was updated successfully, but these errors were encountered: