2
votes

I have this piece of code that calls a web service and displays the names coming from that WS into a Dropdown component from Material UI,

What I want to do is to set the default value of the dropdown with the first element coming from the WS and also be able to select any of the options in dropdown, I read something about "State" but don't get it really good at a code level.

I'm new to React and learning by myself but some help would be nice.

    import React, { Component } from 'react';
    import DropDownMenu from 'material-ui/DropDownMenu';
    import MenuItem from 'material-ui/MenuItem';

    export default class WebserviceTest extends Component {

      constructor(props) {
        super(props);
        this.state = {
        data: [],
       };
       this.renderOptions = this.renderOptions.bind(this);
     }

     componentDidMount() {
     const url = 'https://randomuser.me/api/?results=4';

     fetch(url)
       .then(Response => Response.json())
       .then(findResponse => {
         console.log(findResponse);
         this.setState({
           data: findResponse.results
         });
       });
    }
    //will set wahtever item the user selects in the dropdown
    handleChange(event, index, value) {this.setState({ value });}
    //we are creating the options to be displayed
    renderOptions() {
     return this.state.data.map((dt, i) => {
       return (
         <div key={i}>
           <MenuItem
             label="Select a description"
             value={dt.name.first}
             primaryText={dt.name.first} />
         </div>
       );
     });
    }

    render() {
     return (
       <div>
         <DropDownMenu value={this.state.name} onChange={this.handleChange}>
           {this.renderOptions()}
         </DropDownMenu>
       </div>
     );
   }
  }

Thanks in advance.

Regards.

2

2 Answers

2
votes

You need to set state of selected dropdown option. And set first value of data as selected value.

componentDidMount() {
 const url = 'https://randomuser.me/api/?results=4';

 fetch(url)
   .then(Response => Response.json())
   .then(findResponse => {
     console.log(findResponse);
     this.setState({
       data: findResponse.results,
       selected: findResponse.results[0].name.first // need to be sure it's exist
     });
   });
}
handleChange(event, index, value) {this.setState({ selected: value });}
.
.
.
render() {
 return (
   <div>
     <DropDownMenu value={this.state.selected} onChange={this.handleChange}>
       {this.renderOptions()}
     </DropDownMenu>
   </div>
 );

}

UPDATED CODE

import React, { Component } from 'react';
import DropDownMenu from 'material-ui/DropDownMenu';
import MenuItem from 'material-ui/MenuItem';

export default class WebserviceTest extends Component {
  constructor() {
    super();
    this.state = {
      data: [],
      selected: '',
    };
    this.renderOptions = this.renderOptions.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  componentDidMount() {
    const url = 'https://randomuser.me/api/?results=4';

    fetch(url)
      .then(Response => Response.json())
      .then(findResponse => {
        console.log(findResponse);
        console.log(findResponse.results[0].name.first);
        this.setState({
          data: findResponse.results,
          selected: findResponse.results[0].name.first // need to be sure it's exist
        });
      });
  }
  handleChange(value) {this.setState({ selected: value });}

  //we are creating the options to be displayed
  renderOptions() {
    return this.state.data.map((dt, i) => {
      return (
        <div key={i}>
          <MenuItem
            value={dt.name.first}
            primaryText={dt.name.first} />
        </div>
      );
    });
  }

  render() {
    return (
      <div>
        <DropDownMenu value={this.state.selected} onChange={this.handleChange}>
          {this.renderOptions()}
        </DropDownMenu>
      </div>
    );
  }
}
1
votes

this.setState controls the variable this.state in a special way. Whenever you use this.setState it will run render again to check for changes accordingly. Your dynamic content that you want to be responsive should be placed in this.state and those should be shown in your render function.

There are many ways to go about solving your question, but the most important principle to use is to place what you currently want to render (or the id/index number) in this.state and use this.setState to change it as needed.

value={this.state.name} should be a single value from your data structure that you return from your fetch, assuming this is what is shown on the screen.

Also, you forgot to bind this.handleChange in your constructor.

Stating props in your constructor is perfectly fine to do. You only do that when you want to use something from this.props in your constructor. You aren't, so it's perfectly safe to leave it as constructor() and super()