繁体   English   中英

如何使用 React Hooks 将此级联下拉 class 组件转换为功能组件?

[英]How can I convert the this cascading dropdown class component to functional one using React Hooks?

我在 class 组件形式中有这个级联下拉列表,它工作正常,但我想用 React Hooks 将它转换为功能性下拉列表。 这是一个国家,State,城市下拉菜单。 当用户 select 国家时,将加载其下的州。 当他们 select 和 state 时,将加载其下的城市。 我已更改构造函数部分以开始使用 state,如下所示。 此外,componentDidMount 已转换为 useEffect。 处理程序也已转换。

但是下面显示表单的渲染部分让我很难过。 当我尝试时,我得到了它没有正确安排的错误。 如何使用它转换容器 div 内的部分this. 与 function 的 rest 同步。 我知道我必须取消this. 但我不知道怎么go 呢? 示例 function 发布在下面。

function LocationDropdown() {
    const [state, setState] = useState({
            countries : [],
            states : [],
            lgas : [],
            selectedCountry : '--Choose Country--',
            selectedState : '--Choose State--'
        });

    useEffect(() => {
  setState(prevState => ({
            ...prevState,
            countries : [
                { name: 'Nigeria', value: 'nigeria', 
                states: [ {name: 'Abia', value: 'abia', 
                lgas: [
                        {name: "Aba", value: 'aba'},
                        {name: "Oru", value: 'oru'},

        ]}, {name: 'Adamawa', value: 'adamawa', 
                lgas: [
                        {name: 'Demsa', value: 'demsa'},
                        {name: 'Fufure', value: 'fufure'},
        ]}, 
    },  
            ]
   }));
}, [])

    changeCountry(event) {
        this.setState({selectedCountry: event.target.value});
        this.setState({states : this.state.countries.find(cntry => cntry.name === event.target.value).states});
    }

    changeState(event) {
        this.setState({selectedState: event.target.value});
        const stats = this.state.countries.find(cntry => cntry.name === this.state.selectedCountry).states;
        this.setState({lgas : stats.find(stats => stats.name === event.target.value).lgas});
    }

    render() {

        return (
            <div id="container">
                <h2>Cascading or Dependent Dropdown using React</h2>
                <div>
                    <Label>Country</Label>
                    <Select placeholder="Country" value={this.state.selectedCountry} onChange={this.changeCountry}>
                        <option>--Choose Country--</option>
                        {this.state.countries.map((e, key) => {
                            return <option key={key}>{e.name}</option>;
                        })}
                    </Select>
                </div>

                <div>
                    <Label>State</Label>
                    <Select placeholder="State" value={this.state.selectedState} onChange={this.changeState}>
                        <option>--Choose State--</option>
                        {this.state.states.map((e, key) => {
                            return <option key={key}>{e.name}</option>;
                        })}
                    </Select>
                </div>

                <div>
                    <Label>LGA</Label>
                    <Select placeholder="LGA" value={this.state.selectedLga}>
                        <option>--Choose LGA--</option>
                        {this.state.lgas.map((e, key) => {
                            return <option key={key}>{e.name}</option>;
                        })}
                    </Select>
                </div>
            </div>
        )
    }
}

export default LocationDropdown;

我改变了你的代码。 我重命名statesetState ,所以它不会与实际状态混淆。 SelectLabel更改为正常的 html 元素,以便我可以测试。

import React, { useEffect, useState } from "react";

function LocationDropdown() {
  const [myData, setMyData] = useState({
    countries: [],
    states: [],
    lgas: [],
    selectedCountry: "--Choose Country--",
    selectedState: "--Choose State--"
  });

  useEffect(() => {
    setMyData(prevState => ({
      ...prevState,
      countries: [
        {
          name: "Nigeria",
          value: "nigeria",
          states: [
            {
              name: "Abia",
              value: "abia",
              lgas: [
                { name: "Aba", value: "aba" },
                { name: "Oru", value: "oru" }
              ]
            },
            {
              name: "Adamawa",
              value: "adamawa",
              lgas: [
                { name: "Demsa", value: "demsa" },
                { name: "Fufure", value: "fufure" }
              ]
            }
          ]
        }
      ]
    }));
  }, []);

  const mergeAndUpdateMyData = newData => {
    setMyData({ ...myData, ...newData });
  };

  const changeCountry = event => {
    mergeAndUpdateMyData({
      selectedCountry: event.target.value,
      states: myData.countries.find(cntry => cntry.name === event.target.value)
        .states
    });
  };

  const changeState = event => {
    const stats = myData.countries.find(
      cntry => cntry.name === myData.selectedCountry
    ).states;
    mergeAndUpdateMyData({
      selectedState: event.target.value,
      lgas: stats.find(stats => stats.name === event.target.value).lgas
    });
  };

  return (
    <div id="container">
      <h2>Cascading or Dependent Dropdown using React</h2>
      <div>
        <label>Country</label>
        <select
          placeholder="Country"
          value={myData.selectedCountry}
          onChange={changeCountry}
        >
          <option>--Choose Country--</option>
          {myData.countries.map((country, key) => {
            return (
              <option value={country.name} key={key}>
                {country.name}
              </option>
            );
          })}
        </select>
      </div>

      <div>
        <label>State</label>
        <select
          placeholder="State"
          value={myData.selectedState}
          onChange={changeState}
        >
          <option>--Choose State--</option>
          {myData.states.map((state, key) => {
            return (
              <option value={state.name} key={key}>
                {state.name}
              </option>
            );
          })}
        </select>
      </div>

      <div>
        <label>LGA</label>
        <select placeholder="LGA" value={myData.selectedLga}>
          <option>--Choose LGA--</option>
          {myData.lgas.map((lga, key) => {
            return (
              <option value={lga.name} key={key}>
                {lga.name}
              </option>
            );
          })}
        </select>
      </div>
    </div>
  );
}

export default LocationDropdown;

编辑:请注意,在 React 中,当您设置 state 时,语句是异步的。 这意味着当您调用 setMyData 时,myData 的值不会立即更新。 因此,您不能连续多次调用 mergeAndUpdateMyData。

顺便说一句,您可以在一个 function 组件中使用多个useState 例如:

const [countries, setCountries] = useState();
const [lgas, setLags] = useState();
...

暂无
暂无

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

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