简体   繁体   English

如何在 React.js 的单个组件中根据选定的国家/地区下拉列表两次填充 State 下拉列表数据?

[英]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.我想根据所选国家/地区填充 state 数据。 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:-附上问题截图:- 在此处输入图像描述

Sandbox Url:- https://codesandbox.io/s/country-state-sibling-issue-rdphoc?file=/src/App.js沙盒 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!感谢您的努力!

To achieve multiple same forms with country and state dependent.实现多个相同的 forms with country 和 state dependent。 You need to create the custom component with those form fields and maintain the state in that.您需要使用这些表单字段创建自定义组件并在其中维护 state。 So it will not affect the main component state.所以不会影响主组件state。

在此处输入图像描述

You can find a working sample at https://codesandbox.io/s/country-state-sibling-issue-forked-9wcmi9?file=/src/App.js您可以在https://codesandbox.io/s/country-state-sibling-issue-forked-9wcmi9?file=/src/App.js找到工作示例

CountryStateFormItems component CountryStateFormItems 组件

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}
            />
          ))
        : ""}
    </>
  );
}

You can use two state variables for storing both countries.您可以使用两个 state 变量来存储这两个国家。 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.同样,您也可以使用 2 个变量来存储国家/地区的state值。


Alternatively, you can also store it in a single state object with multiple keys, something like:或者,您也可以将其存储在带有多个密钥的单个 state object 中,例如:

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

You need to manage an array of objects in your state. Here's a good resource that explains how to do it: Managing State Array .您需要管理 state 中的对象数组。这里有一个很好的资源来解释如何做到这一点: 管理 State 数组 I hope it helps!我希望它有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM