react-autosuggest icon indicating copy to clipboard operation
react-autosuggest copied to clipboard

Input field caret position always resets to the end of the input

Open kromit opened this issue 7 years ago • 7 comments

The bug is testable with the Scrollable container example on http://react-autosuggest.js.org/

To reproduce:

  1. Focus on the input field
  2. Type ac
  3. Place the caret between a and c
  4. Type b

Observed behavior:

The caret jumps to the end.

Expected behavior:

The caret should stay between b and c.

kromit avatar Jul 12 '17 09:07 kromit

Thanks for the issue 👍

Looks like a bug!

I guess it's probably related to alwaysRenderSuggestions being true, because this is the only example there that sets it to true, and the bug is not happening in the other examples.

PR is welcome!

moroshko avatar Jul 12 '17 09:07 moroshko

Getting rid of the Modal component solves the problem; it doesn't appear to be related to alwaysRenderSuggestions.

jmlag avatar Sep 07 '17 19:09 jmlag

I've made some research on this. Like @jmlag already said, the problem is not alwaysRenderSuggestions, i guess it is the re-rendering of the component and the inner input element.

If the Autosuggest uses the value from the internal component state, it works, but if the onChange does propagate the newValue to a higher order component like redux-form in my case, ~~it does not work anymore.~~ it does not always work.

onChange=(event, { newValue, method })=> {
        event.preventDefault();
        const {onChange} = this.props;
        onChange(newValue)
}

render(){
        const {value} = this.props;
        const inputProps = {
            value:value
            onChange:this.onChange
        };

     return(
            <AutoSuggest
                inputProps={inputProps}
                suggestions={this.state.suggestions}
      ...
}

kromit avatar Sep 27 '17 10:09 kromit

I am seeing this same issue using react-autosuggest with redux-form. Here's a minimal example (minus the redux store/provider boilerplate):

const SuggestComponent = ({ input }) =>
  <Autosuggest
    suggestions={[]}
    onSuggestionsFetchRequested={() => {}}
    onSuggestionsClearRequested={() => {}}
    inputProps={input}
  />;

const Form = reduxForm({ form: 'foo' })(() =>
  <Field name="bar" component={SuggestComponent} />
);

Rendering Form results in an text input where the caret always jumps to the end.

Maybe worth seeing if any use of Redux (e.g. connect()) causes this behavior, or if it's just redux-form.

keeth avatar Oct 07 '17 08:10 keeth

According to https://github.com/facebook/react/issues/955 it's react behavior

basecoplan avatar Apr 18 '18 12:04 basecoplan

I happened to encounter this behavior recently. If your are using react-autosuggest with redux-form, here is a workaround for you.

Thanks to advices from https://github.com/facebook/react/issues/955

Demo

https://codesandbox.io/s/0o7wpk6ywv

Code

Wrapping react-autosuggest in component:

class MyInput extends React.PureComponent {
  state = { value: "" };

  UNSAFE_componentWillReceiveProps = props => {
    this.setState({ value: props.input.value });
  };

  onChange = (e, { newValue }) => {
    e.persist();
    this.setState({ value: newValue }, () => {
      this.props.input.onChange(e, newValue);
    });
  };

  render() {
    const inputProps = {
      ...this.props.input,
      value: this.state.value,
      onChange: this.onChange
    };
    return (
      <Autosuggest
        suggestions={[]}
        onSuggestionsFetchRequested={() => {}}
        onSuggestionsClearRequested={() => {}}
        inputProps={inputProps}
      />
    );
  }
}

And combining with redux-form:

const SimpleForm = props => {
  const { handleSubmit } = props;
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>First Name</label>
        <div>
          <Field name="firstName" component={MyInput} />
        </div>
      </div>
    </form>
  );
};

export default reduxForm({
  form: "simple" // a unique identifier for this form
})(SimpleForm);

This should be enough for handling change of value with keyboard events or redux-form's action creator (e.g. change, initialize, reset...).

Remember it's still not working with normalization since normalization is a totally new transformation for the value.

Note

UNSAFE_componentWillReceiveProps is intentionally used here. For some unknown reasons it doesn't work with static getDerivedStateFromProps(props, state).

zushenyan avatar Oct 25 '18 15:10 zushenyan

I have a very similar caret behaviour To reproduce:

Focus on the input field Type ac Place the caret between a and c delete a Observed behavior:

The caret jumps to the end.

ghost avatar Jul 16 '20 09:07 ghost