Came across an error with focusInputOnSuggestionClick when trying to automatically focus the input field.
https://codepen.io/marclemagne/pen/RjRdvr
renderInputComponentref to the input on the class (e.g., autosuggestInput)c, and wait for suggestions to appearautosuggest.js:698 Uncaught TypeError: Cannot read property 'focus' of undefined
at Object.onSuggestionClick [as onClick] (autosuggest.js:698)
at Item._this.onClick (autosuggest.js:2941)
at Object.ReactErrorUtils.invokeGuardedCallback (react-dom.js:9017)
at executeDispatch (react-dom.js:3006)
at Object.executeDispatchesInOrder (react-dom.js:3029)
at executeDispatchesAndRelease (react-dom.js:2431)
at executeDispatchesAndReleaseTopLevel (react-dom.js:2442)
at Array.forEach (<anonymous>)
at forEachAccumulated (react-dom.js:15423)
at Object.processEventQueue (react-dom.js:2645)
Questions I have:
Thanks!
Are you using renderInputComponent only to autofocus the input?
If yes, check out this example that doesn't use renderInputComponent.
If you really want to customize the input, here is how you should access it: Codepen
@moroshko I'm getting the same error often. I need to use Material-UI Next TextField. It's a functional stateless component, so I had to wrap it, so refs can be attached to it. But it still throws the above error.
import TextField from 'material-ui/TextField'
// Wrap function or functional stateless component as react class component.
// Useful e.g. if you need to reference the component in React 16.
class Componentize extends React.Component<any, null> {
public render() {
const { Component, component, ...props } = this.props
return Component ? <Component {...props} /> : component(props)
}
}
const renderInput = props => <Componentize Component={TextField} {...props} />
It's at https://github.com/moroshko/react-autosuggest/blob/master/src/Autosuggest.js#L382
Thanks, @moroshko! Sorry I'm just returning to this now.
Some follow-up with my experience and how (for better or worse) I was able to get things working.
Initially, I was working with an input styled-component and my goal was to have it focus automatically.
public input: HTMLInputElement;
public componentDidMount() {
this.input.focus();
}
public storeInputReference = (autosuggest) => {
if (autosuggest != null) {
this.input = autosuggest.input;
}
}
public renderInputComponent = (inputProps) => {
return (
<TextInput {...inputProps} innerRef={inputProps.ref} ref={null} />
);
}
And in the Autosuggest component add:
renderInputComponent={this.renderInputComponent}
ref={this.storeInputReference}
Note the innerRef in the renderInputComponent method. This is what allows you to access the input element within a styled-component.
I am (still) not actually 100% clear on what the ref={null} is for, but everything was working as I needed. I saw it in another issue thread.
Eventually I extended our TextInput component to focus or select itself which added a complication with my usage of AutoSuggest.
I upgraded the styled-component to be a React class component and had it create its own local ref in order to focus/select.
What I was doing above no longer worked. The TextInput would focus, as expected, and AutoSuggest would function nicely after removing the focus-related code in the AutoSuggest parent class鈥攂ut I was back to getting the JavaScript TypeError.
So here's what I am doing now:
I removed ref={this.storeInputReference} from the Autosuggest component. I removed the componentDidMount lifecycle method, as well.
public input: HTMLInputElement;
public renderInputComponent = (inputProps) => {
return (
<TextInput
focused
{...inputProps}
getRef={(input) => this.input = input}
ref={() => inputProps.ref(this.input)}
/>
);
}
In our TextInput component I added a new prop called getRef which returns its local version of this.input in its componentDidMount lifecycle method. In TextInput this.input ref is set in the standard way (ref={input => this.input = input}).
Back to where I'm using AutoSuggest, I noticed that inputProps.ref was returning a function no matter if ref={...} was a prop on Autosuggest or not. So I am using the getRef prop from my TextInput component to get the TextInput input ref and setting that reference locally where I'm using AutoSuggest. Then in the ref prop being passed into TextInput, I am calling that inputProps.ref function to (ostensibly) let Autosuggest know about the reference to the input.
No more error and everything is working correctly.
It's not exactly elegant but it seems to be working. I am sure there has got to be a cleaner, simpler way to achieve this. At the end of the day, though, it seems that AutoSuggest needs a reference to the input or it's going to throw an error.
I am wondering if AutoSuggest should do an existence check on this.input before trying to focus using it.
I hope this proves to be somewhat helpful for anybody else having similar issues.
@marclemagne Thanks so much for that last comment. There's like a dozen issues around refs, but this one finally solved it for _me_. Debugging a custom input that is a styled-component, not necessarily needing the ref as you do, ref={null} was the key.
Most helpful comment
Thanks, @moroshko! Sorry I'm just returning to this now.
Some follow-up with my experience and how (for better or worse) I was able to get things working.
Initially, I was working with an
inputstyled-component and my goal was to have it focus automatically.And in the
Autosuggestcomponent add:Note the
innerRefin therenderInputComponentmethod. This is what allows you to access theinputelement within a styled-component.I am (still) not actually 100% clear on what the
ref={null}is for, but everything was working as I needed. I saw it in another issue thread.Eventually I extended our
TextInputcomponent to focus or select itself which added a complication with my usage of AutoSuggest.I upgraded the styled-component to be a React class component and had it create its own local ref in order to focus/select.
What I was doing above no longer worked. The
TextInputwould focus, as expected, and AutoSuggest would function nicely after removing the focus-related code in the AutoSuggest parent class鈥攂ut I was back to getting the JavaScript TypeError.So here's what I am doing now:
I removed
ref={this.storeInputReference}from theAutosuggestcomponent. I removed thecomponentDidMountlifecycle method, as well.In our
TextInputcomponent I added a new prop calledgetRefwhich returns its local version ofthis.inputin itscomponentDidMountlifecycle method. InTextInputthis.inputref is set in the standard way (ref={input => this.input = input}).Back to where I'm using AutoSuggest, I noticed that
inputProps.refwas returning a function no matter ifref={...}was a prop onAutosuggestor not. So I am using thegetRefprop from myTextInputcomponent to get theTextInputinputref and setting that reference locally where I'm using AutoSuggest. Then in therefprop being passed intoTextInput, I am calling thatinputProps.reffunction to (ostensibly) letAutosuggestknow about the reference to theinput.No more error and everything is working correctly.
It's not exactly elegant but it seems to be working. I am sure there has got to be a cleaner, simpler way to achieve this. At the end of the day, though, it seems that AutoSuggest needs a reference to the input or it's going to throw an error.
I am wondering if AutoSuggest should do an existence check on
this.inputbefore trying to focus using it.I hope this proves to be somewhat helpful for anybody else having similar issues.