Search code examples
javascriptreactjsreact-hook-formcascadingdropdown

Cascading Select not working in Reactjs React-hook-form


I am new to Reactjs and trying to implement cascading dropdowns so that when user select state he will be able to get corresponding cities in next dropdown.

Expected result : For state: Maharashtra -> Cities : Nagpur, Pune

This is my structure of data in data.js

let arr = [
  {
    "state": "Maharashtra",
    "state_code": "mh",
    "cities": [
      {
        "name": "Nagpur",
        "code": "ng"
      },
      {
        "name": "Pune",
        "code": "pu"
      }
    ]
  },
  {
    "state": "Punjab",
    "state_code": "pj",
    "cities": [
      {
        "name": "Chandigarh",
        "code": "hd"
      },
      {
        "name": "Patiala",
        "code": "pt"
      }
    ]
  },
  {
    "state": "Jharkhand",
    "state_code": "jk",
    "cities": [
      {
        "name": "Ranchi",
        "code": "rc"
      },
      {
        "name": "Dhanbad",
        "code": "db"
      }
    ]
  },
  {
    "state": "Telangana",
    "state_code": "ts",
    "cities": [
      {
        "name": "Hyderabad",
        "code": "hd"
      },
      {
        "name": "Amravati",
        "code": "am"
      }
    ]
  }
]

export default arr;

And here's my component component.js

import React from "react";
import "../styles/App.scss";
import { useForm } from "react-hook-form";
import classNames from "classnames";
import arr from "../../src/data"


let finalCities = [];

...

const getCity = (evt) => {
    console.log(evt.target.value);


    arr.forEach(x => {
      if (x.state == evt.target.value) {
        console.log(x.cities);
        finalCities = x.cities
      }
    })

  }

...

    return(
<div>
                  <div className="form-group">
                    <select className="custom-select" name="state" {...register("address.state")} onSelect={getCity}>
                      {arr.map((e, key) => {
                        return <option key={key} value={e.value}>{e.state}</option>;
                      })}
                    </select>
                  </div>
    
                  {/* finalCities */}
                  <div className="form-group">
                    <label htmlFor="City">City</label>
                    <select  value={finalCities} className="custom-select" name="address.city" {...register("address.city")}>
                      {finalCities.map((e) => {
                        return <option key={e} value={e}>{e}</option>;
                      })}
                      {/* {finalCities} */}
                    </select>
                  </div>
</div>
    
    )

Solution

  • It is not problem of React hooks or forms. Understand the concept of states in react.

    import React, { useState } from "react";
    import arr from "../data";
    
    const About = () => {
      const StateList = arr;
      let citiesList = [];
    
      const [cities, setCities] = useState([]);
      const [stateName, setstateName] = useState(arr[0].state);
      const [cityName, setcityName] = useState();
    
      const getCities = (event) => {
        console.log("State:" + event.target.value);
        for (let i = 0; i < StateList.length; i++) {
          if (StateList[i].state == "" + event.target.value)
            citiesList = StateList[i].cities;
        }
        console.log("cityList" + citiesList);
        setCities(citiesList);
        setstateName(event.target.value);
        setcityName(citiesList[0].name);
      };
    
      const refreshCityName = (event) => {
        setcityName(event.target.value);
      };
    
      return (
        <div>
          <div>
            <h2>City List</h2>
            <select name="StateList" onChange={getCities}>
              {StateList.map((e, key) => {
                return (
                  <option key={key} value={e.state}>
                    {e.state}
                  </option>
                );
              })}
            </select>
            {stateName}
          </div>
          <h2> Cities</h2>
          <div>
            <select name="CityList" onChange={refreshCityName}>
              {cities.map((e, key) => {
                return (
                  <option key={key} value={e.name}>
                    {e.name}
                  </option>
                );
              })}
            </select>
            {cityName}
          </div>
        </div>
      );
    };
    
        export default About;