'React suggestions Input setting state

im prety new to React and im trying to use an autocomplete input. Im having problems getting the value from it and clearing the input values after submitting. Any help would be greatly appretiated.

import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";
import "../AutoComplete/styles.css"

class Autocomplete extends Component {

    static propTypes = {
        suggestions: PropTypes.instanceOf(Array)
    };

    static defaultProps = {
        suggestions: [],
    };

    constructor(props) {
        super(props);

        this.state = {
            // The active selection's index
            activeSuggestion: 0,
            // The suggestions that match the user's input
            filteredSuggestions: [],
            // Whether or not the suggestion list is shown
            showSuggestions: false,
            // What the user has entered
            userInput: this.props.value ? this.props.value : "",
        };
    }
  
    //Order by 'code'
    generateSortFn(prop, reverse) {
        return function (a, b) {
            if (a[prop] < b[prop]) return reverse ? -1 : 1;
            if (a[prop] > b[prop]) return reverse ? 1 : -1;
            return 0;
        };
    }

    onChange = e => {
        const { suggestions } = this.props;
        const userInput = e.currentTarget.value;

        // Filter our suggestions that don't contain the user's input
        const filteredSuggestions = suggestions.sort(this.generateSortFn('code', true)).filter(
            (suggestion, i) => { 
                let aux = suggestion.descrp+"- "+suggestion.code
                return aux.toLowerCase().indexOf(userInput.toLowerCase()) > -1
            }
        );

        this.setState({
            activeSuggestion: 0,
            filteredSuggestions,
            showSuggestions: true,
            userInput: e.currentTarget.value
        });
    };

    onClick = e => {
        this.setState({
            activeSuggestion: 0,
            filteredSuggestions: [],
            showSuggestions: false,
            userInput: e.currentTarget.innerText
        });
    };

    onKeyDown = e => {
        const { activeSuggestion, filteredSuggestions } = this.state;

        // User pressed the enter key
        if (e.keyCode === 13) {
            this.setState({
                activeSuggestion: 0,
                showSuggestions: false,
                userInput: filteredSuggestions[activeSuggestion].code+" - "+filteredSuggestions[activeSuggestion].descrp
            });
        }

        // User pressed the up arrow
        else if (e.keyCode === 38) {
            if (activeSuggestion === 0) {
                return;
            }

            this.setState({ activeSuggestion: activeSuggestion - 1 });
        }
        // User pressed the down arrow
        else if (e.keyCode === 40) {
            if (activeSuggestion - 1 === filteredSuggestions.length) {
                return;
            }
            this.setState({ activeSuggestion: activeSuggestion + 1 });
        }
    };

    render() {
        const {
            onChange,
            onClick,
            onKeyDown,
            state: {
                activeSuggestion,
                filteredSuggestions,
                showSuggestions,
                userInput
            }
        } = this;

        let suggestionsListComponent;

        if (showSuggestions && userInput) {
            if (filteredSuggestions.length) {
                suggestionsListComponent = (
                    <ul className="suggestions">
                        {filteredSuggestions.map((suggestion, index) => {
                            let className="";

                            // Flag the active suggestion with a class
                            if (index === activeSuggestion) {
                                className = "suggestion-active";
                            }
                            return (
                                    <li className={className} key={suggestion.code} onClick={onClick}>
                                        {suggestion.code+" - "+suggestion.descrp}
                                    </li>
                            );
                        })}
                    </ul>
                );
            } else {
                suggestionsListComponent = (
                    <div className="no-suggestions">
                        <p>Sin sugerencias</p>
                    </div>
                );
            }
        }


and the return (this is where i think im wrong)

  return (
            <Fragment>
                <label htmlFor="autocomplete-input" className="autocompleteLabel">{this.props.label}</label>
                <div className="centerInput"> 
                    <input
                        className="autocomplete-input"
                        type="text"
                        onChange={onChange}
                        onKeyDown={onKeyDown}
                        defaultValue={this.props.initState}
                        value= {/* this.props.value ? this.props.value : */ userInput}
                        placeholder={this.props.placeholder}
                        selection={this.setState(this.props.selection)}
            
                    />
                    {suggestionsListComponent}
                </div>
            </Fragment>
        );
    }
}

export default Autocomplete;

What I want is to use this component in different pages, so im passing the "selection" prop and setting the state there. The input is working correctly (searches, gets the value and shows/hide the helper perfectly). The problem is i cant reset this inputs clearing them, and i suspect the error is in here. I get the following warning (even with it somewhat functioning)


Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.

This is the Component usage with useState:

<Autocomplete label='Out cost Center:' placeholder='Set the out cost center' suggestions={dataCostCenterHelper} selection={(text) => setOutCostCenter(text.userInput)} value={outCostCenter} />

and last this is how im tryin to clear the state that is set in "selection":

   const clearData = async () => {
        setOutCostCenter('-');

        // other inputs with the same component
        setOutVendor('-'); 
        setOutRefNumber('-');
    }

This gets called inside the function that handles the button submitting the form. Thanks in advance!



Solution 1:[1]

Looking at the code you posted this line might be the problem:

selection={this.setState(this.props.selection)}

You are updating state directly inside the render method, this is not recommended.

Try using a selection prop or state field and update the prop inside a componenteDidMount life cycle

selection={this.state.selection}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1