How to create a React component of select that in the bind event "change" get the right value that was selected?

1

Good evening!

I'm trying to make a select component that is used more than once inside another Parent component.

To create the "option" tags, I make a map inside the array that I created as a state of the Pai / App class.

So far, it works well. However, when I select an option, it understands that I changed the state that was set to an array, as a single value that in case would be the value I selected.

Follow the code below:

import React, { Component } from 'react';
import './App.css';

class App extends Component {

  constructor (props) {
    super(props)
    this.state = {
      value: '?',
      //list
      typeOfSearch: [
        {
          value: 'animated',
          name: 'animated'
        },
        {
          value: 'debuts',
          name: 'debuts'
        },
        {
          value: 'playoffs',
          name: 'playoffs'
        },
        {
          value: 'teams',
          name: 'teams'
        }
      ],
      //timeframe
      period: [
        {
          value: 'week',
          name: 'week'
        },
        {
          value: 'month',
          name: 'month'
        },
        {
          value: 'year',
          name: 'year'
        },
        {
          value: 'ever',
          name: 'ever'
        }
      ],
      //timeframe
      amountResults: [
        {
          value: '10',
          name: '10'
        },
        {
          value: '20',
          name: '20'
        },
        {
          value: '30',
          name: '30'
        },
      ],
    }
    this.handleChange = this.handleChange.bind(this);
  }



  handleChange(event) {

    const target = event.target;
    const value = target.value;
    const name = target.name;

    this.setState({
        [name]: value,
    });

    console.log(event.target.value);
  }

  render() {

    const createItem = (item, key) => <option key = {key} value = {item.value}>
     {item.name} </option>;

    return (
      <div className="container">

        <SelectFilter handleChange={this.handleChange} value={this.state.value} name="typeOfSearch">
            {this.state.typeOfSearch.map(createItem)}
          </SelectFilter>

          <SelectFilter handleChange={this.handleChange} value={this.state.value} name="period">
            {this.state.period.map(createItem)}
          </SelectFilter>

          <SelectFilter handleChange={this.handleChange} value={this.state.value} name="amountResults">
            {this.state.amountResults.map(createItem)}
          </SelectFilter>

      </div>
    );
  }
}

class SelectFilter extends Component {
  render(){

    return (<select onChange={this.props.handleChange} value={this.props.value} name= {this.props.name}>
              {this.props.children}
            </select>)
        }
}


export default App;

Thank you very much for any help!

    
asked by anonymous 24.06.2017 / 23:42

1 answer

1

You are almost there, the problem is that you are about to write the array when you should set the value. In practice the code you have creates this:

this.setState({
    typeOfSearch: 'debuts'
});

This is not what you want because typeOfSearch is an array.

Suggestion:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      values: {},
      //list
      typeOfSearch: [
        {
          value: "animated",
          name: "animated"
        },
        {
          value: "debuts",
          name: "debuts"
        },
        {
          value: "playoffs",
          name: "playoffs"
        },
        {
          value: "teams",
          name: "teams"
        }
      ],
      //timeframe
      period: [
        {
          value: "week",
          name: "week"
        },
        {
          value: "month",
          name: "month"
        },
        {
          value: "year",
          name: "year"
        },
        {
          value: "ever",
          name: "ever"
        }
      ],
      //timeframe
      amountResults: [
        {
          value: "10",
          name: "10"
        },
        {
          value: "20",
          name: "20"
        },
        {
          value: "30",
          name: "30"
        }
      ]
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(name, value) {
    this.setState(
      {
        values: {
          ...this.state.values,
          [name]: value
        }
      },
      () => console.log("Novos valores:", this.state.values)
    );
  }

  render() {
    const createItem = (item, key) =>
      <option key={key} value={item.value}>
        {item.name}
        {" "}
      </option>;

    const selects = ["typeOfSearch", "period", "amountResults"].map(name => {
      return (
        <SelectFilter
          handleChange={e => this.handleChange(name, e.target.value)}
          key={name}
          value={this.state.values[name]}
          name="typeOfSearch"
        >
          {this.state[name].map(createItem)}
        </SelectFilter>
      );
    });
    return <div className="container">{selects}</div>;
  }
}

class SelectFilter extends React.Component {
  render() {
    return (
      <select
        onChange={this.props.handleChange}
        value={this.props.value}
        name={this.props.name}
      >
        {this.props.children}
      </select>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>


<div id="container"></div>
    
25.06.2017 / 03:28