Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to populate State dropdown data as per selected Country dropdown two times in a single component in React.js?

I want to populate state data as per selected country. This is working fine.

But I have two use this condition multiple times in a single page. How can I do this?

Issue Screenshot attached:- enter image description here

Sandbox Url:- https://codesandbox.io/s/country-state-sibling-issue-rdphoc?file=/src/App.js

My Code:-

import React, { useState, useEffect } from "react";
import "./styles.css";
import { TextField, MenuItem } from "@mui/material";

export default function App() {
  const body = [
    {
      state_ID: 1,
      state: "Delhi",
      country_ID: 1,
      country_name: "India"
    },
    {
      state_ID: 2,
      state: "Mumbai",
      country_ID: 1,
      country_name: "India"
    },
    {
      state_ID: 3,
      state: "Calgary",
      country_ID: 2,
      country_name: "Canada"
    },
    {
      state_ID: 4,
      state: "Toronto",
      country_ID: 2,
      country_name: "Canada"
    }
  ];
  const [country, setCountry] = useState([]);
  const [state, setState] = useState([]);
  const [selectedCountry, setSelectedCountry] = useState("");

  useEffect(() => {
    const uniqValues = [
      ...new Map(body.map((item) => [item["country_name"], item])).values()
    ];
    setCountry(uniqValues);
    setState(body);
  }, []);

  useEffect(() => {
    const newStates = body.filter(
      ({ country_name }) => country_name === selectedCountry
    );
    console.log(selectedCountry, newStates);
    setState(newStates);
  }, [selectedCountry]);

  useEffect(() => {}, [body, country]);

  return (
    <>
      <TextField
        className="ruleContainer"
        select
        name="Country"
        label="Country"
        variant="outlined"
        size="small"
        onChange={(event) => setSelectedCountry(event.target.value)}
      >
        {country
          ? country.map((opt) => (
              <MenuItem
                key={opt.country_name}
                value={opt.country_name}
                onChange={(value) => setSelectedCountry(value)}
              >
                {opt.country_name}
              </MenuItem>
            ))
          : ""}
      </TextField>
      <TextField
        className="ruleContainer"
        select
        name="state"
        label="State"
        variant="outlined"
        size="small"
        value=""
      >
        {state
          ? state.map((opt) => (
              <MenuItem key={opt.state} value={opt.state}>
                {opt.state}
              </MenuItem>
            ))
          : ""}
      </TextField>
      <hr />

      <TextField
        className="ruleContainer"
        select
        name="Country"
        label="Country"
        variant="outlined"
        size="small"
        onChange={(event) => setSelectedCountry(event.target.value)}
      >
        {country
          ? country.map((opt) => (
              <MenuItem
                key={opt.country_name}
                value={opt.country_name}
                onChange={(value) => setSelectedCountry(value)}
              >
                {opt.country_name}
              </MenuItem>
            ))
          : ""}
      </TextField>
      <TextField
        className="ruleContainer"
        select
        name="state"
        label="State"
        variant="outlined"
        size="small"
        value=""
      >
        {state
          ? state.map((opt) => (
              <MenuItem key={opt.state} value={opt.state}>
                {opt.state}
              </MenuItem>
            ))
          : ""}
      </TextField>
      <hr />
    </>
  );
}

Thanks for your efforts!

like image 938
Rohit Verma Avatar asked Dec 05 '25 17:12

Rohit Verma


2 Answers

To achieve multiple same forms with country and state dependent. You need to create the custom component with those form fields and maintain the state in that. So it will not affect the main component state.

enter image description here

You can find a working sample at https://codesandbox.io/s/country-state-sibling-issue-forked-9wcmi9?file=/src/App.js

CountryStateFormItems component

import { useState, useEffect } from "react";
import { TextField, MenuItem, Box } from "@mui/material";

const body = [
  {
    state_ID: 1,
    state: "Delhi",
    country_ID: 1,
    country_name: "India"
  },
  {
    state_ID: 2,
    state: "Mumbai",
    country_ID: 1,
    country_name: "India"
  },
  {
    state_ID: 3,
    state: "Calgary",
    country_ID: 2,
    country_name: "Canada"
  },
  {
    state_ID: 4,
    state: "Toronto",
    country_ID: 2,
    country_name: "Canada"
  }
];

export default function CountryStateFormItems(props) {
  const [country, setCountry] = useState([]);
  const [state, setState] = useState([]);
  const [selectedCountry, setSelectedCountry] = useState(props.form.country);
  const [selectedState, setSelectedState] = useState(props.form.state);

  useEffect(() => {
    const uniqValues = [
      ...new Map(body.map((item) => [item["country_name"], item])).values()
    ];
    setCountry(uniqValues);
  }, []);

  useEffect(() => {
    const newStates = body.filter(
      ({ country_name }) => country_name === selectedCountry
    );
    setState(newStates);
  }, [selectedCountry]);

  useEffect(() => {
    props.updateForm(props.index, selectedCountry, selectedState);
  }, [selectedState]);

  return (
    <>
      <Box display="flex">
        <TextField
          style={{ flex: 1 }}
          className="ruleContainer"
          select
          name="Country"
          label="Country"
          variant="outlined"
          size="small"
          value={selectedCountry}
          onChange={(event) => setSelectedCountry(event.target.value)}
        >
          {country
            ? country.map((opt) => (
                <MenuItem
                  key={opt.country_name}
                  value={opt.country_name}
                  onChange={(value) => setSelectedCountry(value)}
                >
                  {opt.country_name}
                </MenuItem>
              ))
            : ""}
        </TextField>
        &nbsp;
        <TextField
          style={{ flex: 1 }}
          className="ruleContainer"
          select
          name="state"
          label="State"
          variant="outlined"
          size="small"
          value={selectedState}
          onChange={(event) => setSelectedState(event.target.value)}
        >
          {state
            ? state.map((opt) => (
                <MenuItem
                  key={opt.state}
                  value={opt.state}
                  onChange={(value) => setSelectedState(value)}
                >
                  {opt.state}
                </MenuItem>
              ))
            : ""}
        </TextField>
      </Box>
      <hr />
    </>
  );
}

App component

import React, { useState, useCallback } from "react";
import "./styles.css";
import { Button } from "@mui/material";
import CountryStateFormItems from "./CountryStateFormItems";

export default function App() {
  const [forms, setForms] = useState([]);

  const addForm = () => {
    const existingForms = [...forms];
    existingForms.push({
      country: "",
      state: ""
    });
    setForms(existingForms);
  };

  const updateForm = useCallback(
    (index, country, state) => {
      const existingForms = [...forms];
      existingForms[index].country = country;
      existingForms[index].state = state;
      setForms(existingForms);
    },
    [forms, setForms]
  );

  const printForm = () => {
    console.log(forms);
  };

  return (
    <>
      <Button variant="contained" onClick={addForm}>
        Add
      </Button>
      &nbsp;
      <Button variant="contained" onClick={printForm}>
        Print
      </Button>
      <hr />
      {forms
        ? forms.map((form, index) => (
            <CountryStateFormItems
              key={index}
              index={index}
              form={form}
              updateForm={updateForm}
            />
          ))
        : ""}
    </>
  );
}
like image 98
Dhaval Gajjar Avatar answered Dec 08 '25 07:12

Dhaval Gajjar


You can use two state variables for storing both countries. Eg:

const [selectedCountry1, setSelectedCountry2] = useState("");
const [selectedCountry2, setSelectedCountry2] = useState("");

And similarly, you can use 2 variables for storing the country's state values as well.


Alternatively, you can also store it in a single state object with multiple keys, something like:

const [selectedCountriesObject, setSelectedCountriesObject] = useState({ country1: "", country2: ""});

like image 42
Jatin Ranka Avatar answered Dec 08 '25 06:12

Jatin Ranka



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!