Sunny Hebbar
Sunny Hebbar

Reputation: 175

Keep Autocomplete value when component re-renders React Material UI

I have a SelectForm class component in which I'm using multiple React Material Autocomplete components with nested TextField components to display separate lists of options. The values of the Autocomplete fields are stored in the local state when an option is selected. The idea is that when the user selects the required options and submits the form, the isSubmitted state is set to true and the Results component is rendered, showing the results that match the selection. If the user then hits an 'Edit Configuration' button in the Results component, the isSubmitted state is set to false, which triggers the SelectForm component to be shown again. At this stage, I want the displayed text in the Autocomplete field to be that which is stored in the state (the option that the user initially selected). However, what actually happens is that the label is displayed again in the field, instead of the selected option, even though the option name is still stored in the local state.

I've tried to use the inputValue prop on the Autocomplete field to set the value to the relevant state value. This ensures that the correct value is displayed in the field when the SelectForm component renders again, but the field is no longer editable. I want the user to be able to edit it if needed at that stage.

Here are some snippets of the state and an Autocomplete field. Any help would be extremely appreciated.

State

    constructor(props) {
        super(props);

        this.state = {
            isSubmitted: false,
            form: {
                cpuParent: '',
            }
        }
    }

handleAutoCompleteChange

handleAutocompleteChange = (name, option) => {
    let value = '';
    if (option) {
        value = [option.name]
    }
    this.setState({
        form: {
            ...this.state.form,
            [name]: value
        }
    });
};

Autocomplete Component

{
    cpuParentList &&
    <Autocomplete
        options={cpuParentList}
        name={"cpuParent"}
        getOptionLabel={(option) => option.name}
        onChange={
            (event, value, reason) => {
                this.handleAutocompleteChange("cpuParent", value);
            }
        }
        style={{width: '100%'}}
        renderInput={
            (params) =>
                <TextField
                    {...params}
                    name={"cpuParent"}
                    label={"Select Brand"}
                    variant="outlined"
                />
            }
        />
}

Upvotes: 2

Views: 5788

Answers (1)

Adrian
Adrian

Reputation: 945

I will suppose that your options for Autocomplete are an array of objects, so you must to save the value like an object, not like a string.

In these lines:

handleAutocompleteChange = (name, option) => {
    let value = '';
    if (option) {
        value = [option.name]
    }
...

You were saving value like string array.

SOLUTION

  • You need to save value in object instead of string, because you need a reference.
  • And finally, you need to provide the value for Autocomplete component.

This is a solution code example:

import React from "react";

import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
class TestAutoComplete extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isSubmitted: false,
      form: {
        cpuParent: null
      }
    };
  }

  handleAutocompleteChange = (name, option) => {
   this.setState({
      form: {
        ...this.state.form,
        [name]: option
      }
    });
  };
  render() {
    // DEFAULT CPUPARENTLIST
    const cpuParentList = [{ value: "item1", name: "Item 1" }];
    return (
      <div>
        <Autocomplete
          // PROVIDE VALUE
          value={this.state.form.cpuParent}
          options={cpuParentList}
          name={"cpuParent"}
          getOptionLabel={option => option.name}
          onChange={(event, value, reason) => {
            this.handleAutocompleteChange("cpuParent", value);
          }}
          style={{ width: "100%" }}
          renderInput={params => (
            <TextField
              {...params}
              name={"cpuParent"}
              label={"Select Brand"}
              variant="outlined"
            />
          )}
        />
      <p>Value Selected: {this.state.form.cpuParent ? this.state.form.cpuParent.name : ""}</p>
      </div>
    );
  }
}

export { TestAutoComplete };

Upvotes: 2

Related Questions