2

I am learning React. I am trying to select country value in input box and handlechange event will target the country code and value will select automatically. I did't add functions handlechange and handleClick here as they were not working. Also I am getting different input box for each field. How to get only one input box with dropdown list?

export default class Api extends Component {
        constructor(props) {
          super(props);
      
          this.state = {
            country: [],
            countryCode:''
          };
        }
  componentDidMount() {
    fetch("https://restcountries.eu/rest/v2/all")
      .then((res) => res.json())
      .then((result) => {
        console.log(result);
        console.warn(result);
        this.setState({ country: result });
        console.log("i am in console");
      });
  }

 this.handleClick = this.handleClick.bind(this);
 this.handleInputChange = this.handleInputChange.bind(this);

  render() {
    return (
      <div>
        <h1 className="text-center"> Api</h1>
        <h2> country details</h2>
        <div>
          {this.state.country.map((countries, i) => (
            <div key={i}>
                <label>Select Country</label>
                <select>
                    <option  onClick={this.handleClick}> {countries.name}</option>
                    </select>
               
              <label>Country Code: </label><input type="text" className="m-5" value={countries.callingCodes} onChange={this.handleInputChange} /> 
            
            </div>
          ))}
        </div>
      </div>
    );
  }
}
3
  • because of the input is in map function, so that it will generate many input boxes Commented Feb 5, 2021 at 6:49
  • Can I use forEach instead of map ? Commented Feb 5, 2021 at 6:53
  • @Ash did you have chance to check my answer? Commented Feb 5, 2021 at 13:07

2 Answers 2

2

You can play around with my changes here.

import React, { Component } from "react";

export default class Api extends Component {
  state = {
    countries: [],
    countryName: "",
    countryCode: ""
  };

  handleCountryPick = (event) => {
    event.preventDefault();
    const country = this.state.countries.find(
      (country) => country.name === event.target.value
    );
    this.setState({
      countryCode: country.callingCodes,
      countryName: country.name
    });
  };

  async componentDidMount() {
    const response = await fetch("https://restcountries.eu/rest/v2/all");
    const countries = await response.json();
    this.setState({ countries: countries });
  }

  render() {
    return (
      <div>
        <h1 className="text-center">Api</h1>
        <h2>country details</h2>
        <CountrySelector
          countries={this.state.countries}
          countryName={this.state.countryName}
          onCountryPickHandler={this.handleCountryPick}
        />
        <CountryCodeInput countryCode={this.state.countryCode} />
      </div>
    );
  }
}

const CountrySelector = ({ countryName, countries, onCountryPickHandler }) => {
  const options = countries.map((country) => (
    <option key={country.name} value={country.name}>
      {country.name}
    </option>
  ));
  return (
    <div>
      <select value={countryName || "none"} onChange={onCountryPickHandler}>
        {options}
        <option value="none">None</option>
      </select>
    </div>
  );
};

const CountryCodeInput = ({ countryCode }) => {
  return (
    <div>
      <label>Country Code: </label>
      <input type="text" value={countryCode} />
    </div>
  );
};

Here is what you need to learn to be able to implement from scratch:

  1. data binding is one-way, from parent to child, that is why you need to keep your handler (callback) handleCountryPick in the parent that keeps the state countries, countryName, countryCode.
  2. time when updates happen and which components know what at which moment.

Sequence UML Diagram

Sign up to request clarification or add additional context in comments.

Comments

0

Have a look at what's inside the Array.map() (I renamed your state.country to state.countries as it is an array.)

  handleCountrySelectChange(e) {
    const selectedCountry = e.target.value
    // ...
  }

  handleInputChange(e) {
    const countryCode = e.target.value
    // ...
  }

  return (
    <div>
      <h1 className="text-center">Api</h1>
      <h2>country details</h2>
      <div>
        <div>
          <label>Select Country</label>
          <select onChange={this.handleCountrySelectChange}>
            {this.state.countries.map(country => (
              <option key={country.name} value={country.name}>
                {country.name}
              </option>
            ))}
          </select>
          <label>Country Code: </label>
          <input type="text" className="m-5" onChange={this.handleInputChange} />
        </div>
      </div>
    </div>
  )
}

2 Comments

I edited the code. Can you please tell me how to get country code in handleInputChange() ?
Your edit was rejected. Please don't edit an answer for asking a new question. You can create a JS Fiddle or Code Sandbox example of a follow-up question and ask in the comment. From your edit I could not understand what you're struggling with. Doesn't e.target.value work for you?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.