Open marclemagne opened 7 years ago
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—but 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.
Unbelievable. This error was really not clear to me. But after trying so many things, the solution ended being as simple as moving the ref
that was being assigned from the renderInputComponent
function return to the actual Autosuggest
component.
...
const renderInputComponent = inputCompProps => (
<input
{...inputCompProps}
// ref={inputRef} // NOT HERE
styleName="input-field"
/>
);
return (
<div>
<Autosuggest
id={id}
alwaysRenderSuggestions={alwaysRenderSuggestions}
focusInputOnSuggestionClick={false}
getSuggestionValue={getSuggestionValue}
highlightFirstSuggestion
inputProps={inputProps}
onSuggestionsClearRequested={handleSuggestionsClearRequested}
onSuggestionSelected={handleSuggestionSelected}
onSuggestionsFetchRequested={handleSuggestionsFetchRequested}
ref={inputRef} // GOES HERE
renderInputComponent={renderInputComponent}
renderSuggestion={renderSuggestion}
suggestions={suggestions}
/>
</div>
);
...
Came across an error with
focusInputOnSuggestionClick
when trying to automatically focus the input field.https://codepen.io/marclemagne/pen/RjRdvr
renderInputComponent
ref
to the input on the class (e.g.,autosuggestInput
)c
, and wait for suggestions to appearQuestions I have:
Thanks!