【问题标题】:React Hooks how to call a function after setState finished linearlyReact Hooks如何在setState线性完成后调用函数
【发布时间】:2021-03-19 13:59:41
【问题描述】:

我有一个注册表单组件,我希望每次单击提交按钮时,它都会重置错误验证对象并填充新的。既然setErrors({})async函数,那么在真正完成状态重置后,接下来的验证流程怎么做?

const [name, setName] = React.useState('');
const [email, setEmail] = React.useState('');
const [errors, setErrors] = React.useState<any>({});

function handleSubmit() {
  setErrors({}); // the resetting part

  // Do belows after setErrors({}) is really done
  let newErrors = {};

  if (name.trim() === '') {
    newErrors = {...newErrors, name: 'Name cannot be empty'};
  } else if (name.trim().length < 3) {
    newErrors = {
      ...newErrors,
      name: 'Name length cannot be less than 3 characters',
    };
  }

  if (email.trim() === '') {
    newErrors = {...newErrors, email: 'Email cannot be empty'};
  } else if (
    !/^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(email)
  ) {
    newErrors = {...newErrors, email: 'Email is not valid'};
  }

  setErrors(newErrors);
}

<Button
  mode="contained"
  style={{borderRadius: 0}}
  contentStyle={{padding: 10}}
  uppercase={false}
  onPress={handleSubmit}>
  Daftar
</Button>

【问题讨论】:

  • 是什么让您认为setErrorsasync 函数?我可以向你保证不是。通常,您将使用 useEffect 挂钩,该挂钩依赖于您希望在其后运行效果回调的值更新。仅创建 newErrors 空对象并在函数完成时更新 errors 状态有什么问题?在同一个函数中的两个setErrors 调用就像这样,第二个无论如何都会覆盖第一个,就像它从未发生过一样。
  • 因为我认为它与非钩子 React 的 setState(...) 相同,不是吗?
  • this.setState 也不是 async 函数。不过,它们都在 React 组件生命周期内工作。
  • 我读到了stackoverflow.com/a/36087156/3087119,它说setState 操作是异步的,并且为了提高性能而进行了批处理。所以,我认为setState(...) 调用下面的语句是在setState() 真正完成之前执行的。
  • 异步代码与async 声明的函数不同。 React 状态更新是异步的,这意味着,它们在渲染周期内排队,并在下一个渲染周期进行批处理。状态是const渲染周期。将状态更新入队的函数是 100% 好的老式同步函数。 setErrors 下面的代码在状态更新之前执行,但这并不重要,因为您将另一个状态更新排入队列,它会覆盖第一个状态。

标签: reactjs react-hooks use-effect


【解决方案1】:

我建议添加名为submitted 的状态属性,当它为真时,它允许显示错误并观察输入值以填充错误:

import React from 'react';

const Untitled = () => {
    const [name, setName] = React.useState('');
    const [email, setEmail] = React.useState('');
    const [errors, setErrors] = React.useState < any > {};
    const [submitted, setSubmitted] = React.useState(false);
    function handleSubmit() {
        setSubmitted(true);
    }

    React.useEffect(() => {
        let newErrors = {};

        if (name.trim() === '' && submitted) {
            newErrors = { ...newErrors, name: 'Name cannot be empty' };
        } else if (name.trim().length < 3) {
            newErrors = {
                ...newErrors,
                name: 'Name length cannot be less than 3 characters',
            };
        }

        if (email.trim() === '' && submitted) {
            newErrors = { ...newErrors, email: 'Email cannot be empty' };
        } else if (!/^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(email)) {
            newErrors = { ...newErrors, email: 'Email is not valid' };
        }

        setErrors(newErrors);
    }, [name, email, submitted]);

    React.useEffect(() => {
        if (!errors.name && !errors.email) {
            setSubmitted(false);
        }
    }, [errors]);

    return (
        <div>
            <input type="text" value={name} onChange={e => setName(e.target.value)} />

            <input type="email" value={email} onChange={e => setEmail(e.target.value)} />
            <Button
                mode="contained"
                style={{ borderRadius: 0 }}
                contentStyle={{ padding: 10 }}
                uppercase={false}
                onPress={handleSubmit}
            >
                Daftar
            </Button>

            {submitted && JSON.stringify(errors)}
        </div>
    );
};

export default Untitled;


【讨论】:

    猜你喜欢
    • 2020-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 2020-01-15
    相关资源
    最近更新 更多