【问题标题】:Setting Multiple state using common function in React Hooks使用 React Hooks 中的常用函数设置多个状态
【发布时间】:2020-11-13 22:14:14
【问题描述】:

我在最近的项目中遇到了一个问题,我有一个包含基本用户详细信息的表单,例如 First NameLast NameEmailMobile NoOTP。这些字段是我在react-hook 中创建的状态。 现在我必须编写一个handleInputChange 函数,它将两个参数作为输入,即(label, value),并更新相应的状态该字段的值。

另外,如果我必须在我的handleInputChange中设置状态之前触发我的validation函数,那么如何实现呢。

请向我推荐 optimal 解决方案,以便如果将来我的 UI 中有 10+ 个字段,如何动态更新它们的状态。

下面的代码-sn-p 是我的Class-based 组件,我想通过React-Hooks 在我的functional 组件中实现类似的行为。

初始状态声明:

this.state = {
      name: { value: "", error: "" },
      city: { value: "", error: "" },
      email: { value: "", error: "" },
      contact_number: { value: "", error: "" },
      otp_data: {}
    };

我的handleInputChange函数:

handleInputChange = (name, value) => {
    let label = "";
    this.setState({
      [label]: {
        ...this.state[label],
        value: value,
        error: validateFields(label, value)
      }
    });
  };

【问题讨论】:

标签: javascript reactjs optimization react-hooks react-functional-component


【解决方案1】:

当使用 react 钩子来管理组件的状态时,如果它们不会像这样相互影响,则更常见的是分开属性:

const [name, setName] = React.useState(`default name, can be left empty`)
const [city, setCity] = React.useState(`default city, can be left empty`)

现在您可以通过访问namecity 访问状态,并使用setCity('New York)` 更改它们。

如果您出于某种原因需要像在基于类的组件中那样进行分组,您可以这样做:

const [obj, setObj] = React.useState({name: 'Milorad', city: 'Svrljig'})

现在只需将名称更改为 setObj(prev => ({...prev, name: 'Ilija'})) 或在您有键值对的情况下:

const handleInputChange = (key, value) => {
    setObj(prev => ({...prev,
      [key]: {
        ...prev[key],
        value: value,
        error: validateFields(key, value)
      })
    });
  };

【讨论】:

    【解决方案2】:

    始终建议为每个变量创建单独的状态。在功能组件中,您可以使用 useState 如下

    const [name, setName] = useState({ value: "", error: "" });
    const [city, setCity] = useState({ value: "", error: "" });
    const [email, setEmail] = useState({ value: "", error: "" });
    const [contact_number, setContactNumber] = useState({ value: "", error: "" });
    const [otp_data, setOtpData] = useState({ value: "", error: "" });
    
    // Mapping of label with state changer
    const labelStateMap = {
            name: setName,
            city: setCity,
            email: setEmail,
            contact_number: setContactNumber,
            otp_data: setOtpData
    }
    
    handleInputChange = (label, value) => {
        const stateChanger = labelStateMap[label];
        if(stateChanger){
            stateChanger({
                value,
                error: validateFields(label, value)
            })
        }
      };
    

    【讨论】:

    • 总是建议为每个变量创建单独的状态?
    • 如您所见,我们为每个变量使用了多个 useState。这可以通过使用单个 useState 来完成,整个对象包含所有变量。但不推荐,也无法跟踪变量何时发生变化。
    【解决方案3】:

    您可以考虑使用Formik,而不是编写自己的逻辑,这会让您更轻松。

    【讨论】:

      【解决方案4】:

      使用useState钩子你可以做这样的事情

      制作一个状态变量并将其初始化为初始表单数据

      const [formData, setFormData] = useState({
        name: { value: "", error: "" },
        city: { value: "", error: "" },
        email: { value: "", error: "" },
        contact_number: { value: "", error: "" },
        otp_data: {},
      });
      

      为了应对变化,

      handleInputChange = (event) => {
        const { name, value } = event.target;
        setFormData({
          ...formData,
          [label]: {
            value,
            error: validateFields(label, value),
          },
        });
      };
      

      handleChange 函数的输入调用钩子返回的setFormData 函数并覆盖更改输入的表单数据。

      【讨论】:

        猜你喜欢
        • 2020-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-02
        • 2019-11-18
        相关资源
        最近更新 更多