Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting a default value on a react select dropdown that is populated from an API call

class Select extends React.PureComponent {
    constructor(props) {
        super(props)
        this.state = { value: this.props.defaultValue }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(e) {
        e.persist()
        if (typeof this.props.onDataChange !== 'undefined') {
            this.setState({ value: e.target.value }, () => this.props.onDataChange(e))
        } else {
            this.setState({ value: e.target.value })
        }
    }

    render() {
        const { options } = this.props
        return (
            <div>
                <select
                    value={this.state.value}
                    onChange={this.handleChange}
                >
                    {options.map((option, i) => {
                        const value = option.value || option.path || null
                        const label = option.label || option.name || option

                        return (
                            <option key={`option-${i}`} value={value}>
                                {label}
                            </option>
                        )
                    })}
                </select>
            </div>
        )
    }
}

class Display extends React.PureComponent {
    constructor(props) {
        super(props)
    }

    async getSomeValues() {
        try {
            this.setState({ isReady: false })
            await Axios.get(`some-values`)
                .then(async (result) => {
                    this.setState({
                        values: result.data.values,
                        default: result.data.default
                    })
                })
        } catch (error) {
            console.log(error)
        } finally {
            this.setState({ isReady: true })
        }
    }

    componentDidMount() {
        this.getSomeValues()
    }

    render() {
        return (
            <Select 
                options={this.state.values} 
                defaultValue = {this.state.defaultValue} 
            />
        )
    }
}

I'm trying to solve what i believe to be a pretty simple problem. I have a parent component that houses a child component which is rending a select dropdown.

My parent makes a call to an API service and pulls back a list of items that are to be displayed in the select dropdown. My API returns the set of options to be displayed and an initial value to be selected on load.

The initial render takes the defaultValue property and sets the state to be displayed in the initial instance in the select component constructor, the problem i have with this, is that the api call is done after the initial render so the default value always comes out being null.

I need a mechanism to set the value of the select dropdown to an initial value on load but it has to be done as a result of the api call that happens once the component has loaded?

What is the cleanest way to set the state value to whatever is returned from the API on initial load?

I'm sure this must be an easy problem to solve but i keep getting stuck between what i want to do and the load / render patterns in react.

Any help would be appreciated.

like image 857
ahammond Avatar asked Nov 01 '19 16:11

ahammond


People also ask

How do you set a default value in React?

To set a default value for an input element in React: Pass the default value as a parameter to the useState hook for controlled fields. Set the defaultValue prop on uncontrolled input fields.

How reset dropdown selected value in React select?

You can clear the value of react select using the ref. Just store the value in the state, and change the state programmatically using componentDidUpdate etc... Note: 'value' should be an object. A simple option would be to pass null to the value prop.

How do I set the default option in select?

The default value of the select element can be set by using the 'selected' attribute on the required option. This is a boolean attribute. The option that is having the 'selected' attribute will be displayed by default on the dropdown list.


1 Answers

I see two options:

Option 1

You can prevent the rendering of your Select component until the request is finished. This will mean your constructor will fire after you have the data and will be initialized correctly.

render() {
  if (this.state.defaultValue) {
    return (
      <Select 
        options={this.state.values} 
        defaultValue={this.state.defaultValue} 
      />
    )
  } else {
    return null; // or loading graphic
  }
}

Option 2

In your Select component, use a lifecycle method like componentDidUpdate to check if the defaultValue prop has changed from the last render. If so, set the default value in state. This will make it so that defaultValue only gets set once.

componentDidUpdate(prevProps) {
  if (this.props.defaultValue !== prevProps.defaultValue) {
    this.setState({ defaultValue: this.props.defaultValue });
  }
}
like image 166
Brian Thompson Avatar answered Oct 23 '22 04:10

Brian Thompson