React-autosuggest: 'input.focus is not a function' when using a custom component as the input.

Created on 27 Jan 2017  路  6Comments  路  Source: moroshko/react-autosuggest

__codepen__
http://codepen.io/dancoates/pen/JErmeO?editors=0010

__steps to replicate__

  • enter something in autosuggest box
  • select item from the list __by clicking on it__
  • there will be an error in the console along the lines of 'input.focus is not a function'

This seems to happen when using a custom renderInputComponent function that returns a custom input component. It doesn't seem to actually break the autosuggest but doesn't focus the input and may cause subtle issues that I haven't noticed yet.

Most helpful comment

Above is correct, I wanted to give an example using a custom component:

  const renderInputComponent = inputProps => {
    return <TextInput {...inputProps} refCallback={inputProps.ref} ref={null} />;
  };
  ...
  render() {
    return <Autosuggest renderInputComponent={props.renderedInputComponent} {...props} />
  }
  ...
  TextInput = props => <div><input ref={props.refCallback} /></div>;

The trick here is ref={null} otherwise the autosuggest input gets set twice, first to the input then to the TextInput component - and focus blows up.

All 6 comments

Docs suggest that renderInputComponent should pass through all the provided inputProps to the input element.

The problem is that you don't pass inputProps.ref to the input field.
Your InputComponent swallows the ref.

You could solve it like this.

Ah, thanks. I totally missed that the InputComponent would be swallowing the ref.

Above is correct, I wanted to give an example using a custom component:

  const renderInputComponent = inputProps => {
    return <TextInput {...inputProps} refCallback={inputProps.ref} ref={null} />;
  };
  ...
  render() {
    return <Autosuggest renderInputComponent={props.renderedInputComponent} {...props} />
  }
  ...
  TextInput = props => <div><input ref={props.refCallback} /></div>;

The trick here is ref={null} otherwise the autosuggest input gets set twice, first to the input then to the TextInput component - and focus blows up.

A note for styled-components users who stumble across this. You can't spread the inputProps, since the inputProps contains a ref attribute that, in styled-components, needs to be innerRef. Do something along these lines:

innerRef={inputProps.ref}

And for those finding this, styled-components v4 dropped innerRef for normal ref https://www.styled-components.com/docs/api#deprecated-innerref-prop

If anyone has stumbled upon this and the current solutions aren't working, try the one outlined here in reference to integrating react-isolated-scroll https://github.com/moroshko/react-autosuggest/blob/b8de1d45d154e49b83d6bd7c9de29d5133c2f7fb/FAQ.md

My working solution using react-mdl's Textfield component:

const AutosuggestInput = (textFieldProps) => {
  // Capture the input's ref sent from Autosuggest's `renderInputComponent`
  const { ref, ...inputProps } = textFieldProps

  // Textfield's input ref is stored in its `this.inputRef` property
  // So we need to bubble that up here for Autosuggest to use as its `this.input`
  const callRef = (mdlTextField) => {
    if (mdlTextField !== null) {
      ref(mdlTextField.inputRef)
    }
  }

  return <Textfield {...inputProps} ref={callRef} />
}

const MainComponent = (props) => {
  return <Autosuggest renderInputComponent={AutosuggestInput} />
}

Using this, no other capturing of ref is necessary. Autosuggest's internal this.input will be whatever you passed to ref(mdlTextField.inputRef)

Seems like the trick is less about swapping Autosuggest's ref with your custom one (to avoid it being swallowed), and more about _calling it_ with your custom ref.

Was this page helpful?
0 / 5 - 0 ratings