Skip to content
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

Input value lost when method === 'click' #601

Open
bildungsroman opened this issue Jan 10, 2019 · 2 comments
Open

Input value lost when method === 'click' #601

bildungsroman opened this issue Jan 10, 2019 · 2 comments

Comments

@bildungsroman
Copy link

Are you reporting a bug? Yes

  • Please create a Codepen that demonstrates your issue.
    I'm not able to create a codepen, as this code is running in our own wrapper component in a private repo. I'll do my best to reproduce the relevant code here.

I'm hitting an issue specifically when the selection method is 'click' (rather than 'down' and 'tab' or 'enter' or manually filling out the value): the value is not saved in state, and shows as null. I know this is an issue specifically with my autosuggest component, as manually filling in the value works as expected and is saved in state.

  • Provide the steps to reproduce the issue, e.g.:

    1. Focus on the input field
    2. Type c, and wait for suggestions to appear
    3. Click on one of the suggestions

    Observed behaviour: The suggestion appears as it should in the field, but its value is not passed to state, and my app throws an error because an expected string is actually null.

    Expected behaviour: The value is passed from the autosuggest field to state no matter how it is entered, whether clicking on the suggestion or hitting down and enter to select the suggestion.

Here is the relevant code from my component:

import React, { Component } from 'react';
import Autosuggest from 'react-autosuggest';

const Suggestion = suggestion => <span>{suggestion}</span>;

class AutoSuggest extends Component {
  constructor (props) {
    super(props);

    this.state = {
      suggestions: props.suggestions,
      value: props.value || ''
    };

    this.getSuggestions = this.getSuggestions.bind(this);
    this.onSuggestionsFetchRequested = this.onSuggestionsFetchRequested.bind(this);
    this.onSuggestionsClearRequested = this.onSuggestionsClearRequested.bind(this);
    this.onChange = this.onChange.bind(this);
  }

  getSuggestions (value) {
    const inputValue = value.trim().toLowerCase();
    const inputLength = inputValue.length;

    return inputLength === 0 ? [] : this.props.suggestions.filter(suggestion =>
      suggestion.toLowerCase().includes(inputValue) && suggestion.toLowerCase() !== inputValue
    );
  }

  // Autosuggest will call this function every time you need to update suggestions.
  onSuggestionsFetchRequested ({ value }) {
    this.setState({
      suggestions: this.getSuggestions(value)
    });
  }

  // Autosuggest will call this function every time you need to clear suggestions.
  onSuggestionsClearRequested () {
    this.setState({
      suggestions: []
    });
  }

  onSuggestionSelected (event, { method }) {
    if (method === 'enter') {
      event.preventDefault();
    }
  }

  onChange (event, { newValue }) {
    /* The Autosuggest component doesn't always have the name attribute set on
     * the event target. We must set the name on the target of the event to
     * ensure the value is saved correctly. */
    event.target.name = this.props.name;
    event.target.value = newValue;

    // this is not working when method === 'click'
    this.setState({ value: newValue });

    this.props.onChange(event);
  }

  render () {
    const {
      suggestions,
      value
    } = this.state;

    const {
      placeholder,
      required,
      name,
      pattern,
      readOnly
    } = this.props;

    return (
      <Autosuggest
        suggestions={suggestions}
        getSuggestionValue={suggestion => suggestion}
        onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
        onSuggestionsClearRequested={this.onSuggestionsClearRequested}
        onSuggestionSelected={this.onSuggestionSelected}
        renderSuggestion={Suggestion}
        inputProps={{ onChange: this.onChange, placeholder, value, required, name, pattern, readOnly }}
      />
    );
  }
}

export default AutoSuggest;
@ghost
Copy link

ghost commented Sep 23, 2019

Any update? I am facing this issue also.

@barbel-thierry
Copy link

A bit late, but the problem is that newValue is undefined when 'click' method is used.

Just modify the value to set in your onChange function:

this.setState({ value: newValue ?? event.target.firstChild.data });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants