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

标签 javascript reactjs

我想根据所选国家/地区填充州数据。这工作正常。

但是我有两个在一个页面中多次使用这个条件。我该怎么做?

附上问题截图:- enter image description here

沙盒网址:- https://codesandbox.io/s/country-state-sibling-issue-rdphoc?file=/src/App.js

我的代码:-

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

感谢您的努力!

最佳答案

实现多个与国家和州相关的相同表单。您需要使用这些表单字段创建自定义组件并维护其中的状态。所以不会影响主要组件的状态。

enter image description here

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

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

应用组件

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

关于javascript - 如何在 React.js 的单个组件中根据选定的国家/地区下拉列表两次填充州下拉列表数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73896928/

相关文章:

javascript - 将鼠标悬停时的文本添加到链接、添加过滤和缩放

javascript - 创建一组元素 JointJS

javascript - React中的({})是什么意思?

reactjs - 如何将动画添加到 "react-google-maps"中的标记?

javascript - Preact 粒子

javascript - 如何模拟此 JavaScript 功能(可移动的 div 和保存的位置)

javascript - 未定义的 typescript 对象属性

javascript - 如何使用 jQuery 通过 ajax 调用传递隐藏值?

reactjs - 导入 react 图时,Jest 失败并显示 'self is not defined'

javascript - 如何将自动对焦设置为选择下拉列表中的输入?