0

I am facing one problem with React-Select. I get it's value from calling API. but it's not getting the value that I get by calling API.

import React from "react";
import Select from "react-select";

class SelectValue extends React.Component {
  state = {
    selectedValue: { label: "Select Value", value: this.props.getSelectedValue }
  };

  renderSelectOptions = refundOptions => {
    return <span>{refundOptions.label}</span>;
  };

  onSelectChange = selectedRefund => {
    this.setState({
      selectedValue
    });
  };

  render() {
    return (
      <div>
        <Select
          name="select1"
          placeholder="Select"
          value={this.state.selectedValue.value}
          onChange={this.onSelectChange}
          clearable={false}
          searchable={false}
          optionRenderer={this.renderSelectOptions}
          options={[
            { value: 1, label: "Value 1" },
            { value: 2, label: "Value 2" },
            { value: 3, label: "Value 3" }
          ]}
        />
      </div>
    );
  }
}

I get Value1 in this.props.getSelectedValue.

Where am I lacking?

Any help would be great.

Thank You.

Tholle
  • 108,070
  • 19
  • 198
  • 189
Brijesh Patel
  • 157
  • 1
  • 4
  • 15
  • 1
    `prop` is getting updated after the component is mounted? – Agney Jul 11 '18 at 13:25
  • Possible duplicate of [How to set a default value in react-select](https://stackoverflow.com/questions/43495696/how-to-set-a-default-value-in-react-select) – t3__rry Jul 11 '18 at 13:27
  • @BoyWithSilverWings .. How can I solve this issue ? – Brijesh Patel Jul 12 '18 at 06:43
  • @BrijeshPatel Either mount the component only when you have received data from backend, or write `getDerivedStateFromProps` for your component – Agney Jul 12 '18 at 06:45

3 Answers3

0

if you want to set initial state via props you have to set them inside a constructor with props

so

constructor(props){
    super(props)

      this.state = {
        selectedValue: { label: "Select Value", value:props.getSelectedValue }
      };
}
KornholioBeavis
  • 2,402
  • 2
  • 19
  • 26
  • it's not working. coz before getting data from database , constructor will be called and hence it will not get data in `selectedValue.value.` – Brijesh Patel Jul 12 '18 at 06:42
0

Cam you try this way ?

constructor(props){
     super(props);
      this.state = {
        selectedValue: false,
      }
  }

    componentDidMount = () => {
      this.setState({selectedValue: this.props.getSelectedValue });
    }

    _changeValue = selectedValue => {
        if (selectedValue.value !== null) {
          this.setState({ selectedValue: selectedValue.value });
        }
      }

    render(){
      const { selectedValue } = this.state;
      let values = [{ value: true, label: 'first' }, { value: false, label: 'second' }];

      return(
        <div>
              <Select
                 name="selectedValue"
                 value={selectedValue}
                 onChange={this._changeValue}
                 options={values}
              />
        </div>
      )
    }
Krina Soni
  • 870
  • 6
  • 14
0
  1. Your can choose to mount the select component only when the value from API is returned.

class SelectComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: props.value
    }
  }
  handleChange() {
  }
  render() {
    return (
      <Select
        name="form-field-name"
        value={this.state.value}
        onChange={this.handleChange}
        options={[
          { value: 'one', label: 'One' },
          { value: 'two', label: 'Two' },
        ]}
      />
    );
  }
}


class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null
    }
  }
  componentDidMount() {
    this.getDataFromAPI().then(data=>{
      this.setState({
        value: data
      });
    });
  }
  getDataFromAPI() {
    return new Promise((resolve, reject)=>{
      setTimeout(()=>resolve('one'), 1000);
    });
  }
  render() {
    return (
      <React.Fragment>
        {
          this.state.value &&
            <SelectComponent value={this.state.value} />
        }
        
      </React.Fragment>
    );
  }
}
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.2/prop-types.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.js"></script>
<script src="https://unpkg.com/react-input-autosize@2.0.0/dist/react-input-autosize.js"></script>
<script src="https://unpkg.com/react-select@1.2.1/dist/react-select.js"></script>

<link rel="stylesheet" href="https://unpkg.com/react-select@1.2.1/dist/react-select.css">
<div id="root"></div>
  1. You could choose to keep the state in parent component and reset the state for child component, instead of setting the state there.

class SelectComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <Select
        name="form-field-name"
        value={this.props.value}
        onChange={this.props.handleChange}
        options={[
          { value: 'one', label: 'One' },
          { value: 'two', label: 'Two' },
        ]}
      />
    );
  }
}


class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null
    }
  }
  componentDidMount() {
    this.getDataFromAPI().then(data=>{
      this.setState({
        value: data
      });
    });
  }
  getDataFromAPI() {
    return new Promise((resolve, reject)=>{
      setTimeout(()=>resolve('one'), 1000);
    });
  }
  render() {
    return (
      <React.Fragment>
        <SelectComponent value={this.state.value} handleChange={this.handleChange} />
      </React.Fragment>
    );
  }
}
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.2/prop-types.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.js"></script>
<script src="https://unpkg.com/react-input-autosize@2.0.0/dist/react-input-autosize.js"></script>
<script src="https://unpkg.com/react-select@1.2.1/dist/react-select.js"></script>

<link rel="stylesheet" href="https://unpkg.com/react-select@1.2.1/dist/react-select.css">
<div id="root"></div>
  1. You could also resort to getDerivedStateFromProps to set state to the changed props.

class SelectComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null
    }
  }
  static getDerivedStateFromProps(props, state) {
    if(props.value!==state.value) {
      return {
        value: props.value
      }
    }
    return null;
  }
  handleChange() {
  }
  render() {
    return (
      <Select
        name="form-field-name"
        value={this.state.value}
        onChange={this.handleChange}
        options={[
          { value: 'one', label: 'One' },
          { value: 'two', label: 'Two' },
        ]}
      />
    );
  }
}


class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null
    }
  }
  componentDidMount() {
    this.getDataFromAPI().then(data=>{
      this.setState({
        value: data
      });
    });
  }
  getDataFromAPI() {
    return new Promise((resolve, reject)=>{
      setTimeout(()=>resolve('one'), 1000);
    });
  }
  render() {
    return (
      <React.Fragment>
        <SelectComponent value={this.state.value} />
      </React.Fragment>
    );
  }
}
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.2/prop-types.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.js"></script>
<script src="https://unpkg.com/react-input-autosize@2.0.0/dist/react-input-autosize.js"></script>
<script src="https://unpkg.com/react-select@1.2.1/dist/react-select.js"></script>

<link rel="stylesheet" href="https://unpkg.com/react-select@1.2.1/dist/react-select.css">
<div id="root"></div>
Agney
  • 18,522
  • 7
  • 57
  • 75
  • I still didn't get my answer. I get data in `this.props.getValue`. how can I pass this value to `select` which has preselected value. – Brijesh Patel Jul 18 '18 at 02:57
  • @BrijeshPatel None of the code snippets have your answer? All of them demo using props to set the value of select – Agney Jul 18 '18 at 04:28
  • i have used all your snippets , still i didn't get my desired output. – Brijesh Patel Jul 18 '18 at 10:52
  • @BrijeshPatel How is your case different? The prop arriving asynchronously should set the value for all of the demos. – Agney Jul 18 '18 at 11:58
  • I get value in `this.props.getValue` which I get from parent component so how can I deal this with default value? – Brijesh Patel Jul 18 '18 at 12:29
  • You get the value to set in `this.props.getValue` from the parent and you would like to set this to the Select component? – Agney Jul 18 '18 at 13:21
  • exactly. that's what I want. and I can't put in constructor as it will be called first before the render method. I put the condition that `if(this.props.getValue) then only I render` else I show loader until data is being loaded. – Brijesh Patel Jul 19 '18 at 03:37
  • That is what all three of those demos are doing. @BrijeshPatel – Agney Jul 19 '18 at 04:49
  • thank you so much for your time and effort. still I don't get my desired output.. :( – Brijesh Patel Jul 19 '18 at 05:38