tomsoon95
tomsoon95

Reputation: 3

How to get select option value React

I need a little help with my project. I think it is almost done, but I don't know how to finish...

So, I want to build app with input, select and button. Into input u can write for example, mettalica and after click on button app renders list with all songs, titles and tabTypes(guitar tabs). The problem is that i want to get info from select and render only that songs which includes for example player tabs.

Sandbox Code: https://codesandbox.io/s/react-example-ys6py?fontsize=14&hidenavigation=1&theme=dark

class Search extends React.Component {
  state = {
    searchValue: "",
    songs: [],
    musicTabs: [
      'Dowolne',
      'Bass',
      'Player',
      'Chords',
      'Guitar'
    ],
    result: ''
  };

  handleOnChange = event => {
    this.setState({ searchValue: event.target.value });
  };

  handleSelectChange = (event) => {
    this.setState({
      result: event.target.value
    })
    console.log(this.state.result)
  }

  handleSearch = () => {
    this.makeApiCall(this.state.searchValue);
  };

  makeApiCall = async searchInput => {
    let api_url = `https://www.songsterr.com/a/ra/songs/byartists.json?artists=${searchInput}`;
    const response = await fetch(api_url);
    const songs = await response.json();
    this.setState({ songs });
  };

  render() {
    return (
      <div>
        <Header />
        <input
          name="text"
          type="search"
          placeholder="Search..."
          onChange={event => this.handleOnChange(event)}
          value={this.state.SearchValue}
        />

        <Select optionValue={ this.state.musicTabs } change={ this.handleSelectChange } value={ this.state.result } />

        <br />
        <button onClick={this.handleSearch}>Search</button>


        {this.state.songs ? (
          <div>
            {
              this.state.songs.map((song, index) => (
                <div key={index} className="lists">
                  <h1>Artist: <span>{song.artist.name}</span></h1>
                  <h2>Song title: <span>{song.title}</span></h2>
                  <ol>
                    <b>Available tabs:</b>
                    {song.tabTypes.map((tab, index) =>
                      <li key={index}> {song.tabTypes[index]} </li>
                    )}

                  </ol>

                </div>
              ))


            }
          </div>
        ) : (
            <p>Something</p>
          )}
      </div>
    );
  }
}



const Select = (props) => {
  const { optionValue, change } = props;

  const valueMusicTabs = optionValue.map((musicTab, index) => {
   return <option name={ optionValue[index] } key={ index }> { optionValue[index] } </option>
  })

  return (

    <>
    <select onChange={ change }>
      { valueMusicTabs } 

    </select>

  </>

  )
};

Thanks for help guys!

Upvotes: 0

Views: 384

Answers (4)

Muhammad Zeeshan
Muhammad Zeeshan

Reputation: 4748

I checked the codesandbox, everything was working right. this.setState is an asynchronous function. So, if you will console.log after this.setState chances are your will not log updated value. You can do it like this with a callback function.

handleSelectChange = (event) => {
    this.setState({
      result: event.target.value
    }, () => console.log(this.state.result))
  }

If you want to filter you can do that by making a function like:

filterSongs = selected => {
 return songs.filter(song => song.tabTypes === selected);
}

and After that modify your handleSelectChange as:

handleSelectChange = (event) => {
    let songs = filterSongs(event.target.value);
    this.setState({
      result: event.target.value,
      toDisplay: songs
    }, () => console.log(this.state.result))
  }

and finally in your JSX:

return (
  <>
    {toDisplay.map((song, index) => {
      return <p key={index}>{song.toString()}</p>
    })}
  </>
);

Upvotes: 0

tomsoon95
tomsoon95

Reputation: 3

Thanks for answers! I have last question, where I have to use method to filter that rendered list. If I select "Player" I want to render only that songs, which inlcudes "Player" tab in tabTypes. I still can't get it. I can't do it by changing API link.

Upvotes: 0

Prince Sodhi
Prince Sodhi

Reputation: 2955

If I understand correctly. you want to get the results from API based on selected values of input and select.

as I can see you are only passing the param from input nothing from select.

  handleSearch = () => {
    this.makeApiCall(this.state.searchValue);
  };

  makeApiCall = async searchInput => {
    let api_url = `https://www.songsterr.com/a/ra/songs/byartists.json?artists=${searchInput}`;
    const response = await fetch(api_url);
    const songs = await response.json();
    this.setState({ songs });
  };

The new call will be

let api_url = `https://www.songsterr.com/a/ra/songs/byartists.json?artists=${searchInput}&tabTypes=${selectValue}`; 

I do not know how what are the parameters this API accepts.

Upvotes: 0

Claeusdev
Claeusdev

Reputation: 503

I think you did everything right, just used the wrong prop

<Select optionValue={ this.state.musicTabs } onChange={ this.handleSelectChange } value={ this.state.result } />

the change prop on the Select component should just be changed to onChange since it's a default event it will be passed with the event to your handleChange method

Upvotes: 1

Related Questions