【问题标题】:Updating multiple states in React Native在 React Native 中更新多个状态
【发布时间】:2022-01-22 03:20:52
【问题描述】:

我正在尝试跟踪多个状态(本例中的错误处理),但由于现阶段未知的原因(我认为缺乏理解)我似乎只能保持最后一次错误函数调用的状态:

export const SignUp = () => {
  const [errors, setErrors] = useState({});
  
  const validateFirstName = () => {
    if (formData.firstName === undefined) {
      setErrors(prevState => ({
        ...prevState.firstName,
        firstName: 'First Name is required',
      }));
      return false;
    } else if (formData.firstName.length < 3) {
      setErrors(prevState => ({
        ...prevState.firstName,
        firstName: 'First Name is too short',
      }));
      return false;
    }
    return true;
  };

  const validateLastName = () => {
    if (formData.lastName === undefined) {
      setErrors(prevState => ({
        ...prevState.lastName,
        lastName: 'Last Name is required',
      }));
      return false;
    } else if (formData.lastName.length < 1) {
      setErrors(prevState => ({
        ...prevState.lastName,
        lastName: 'Last Name is too short',
      }));
      return false;
    }
    return true;
  };

  const formSubmitHandler = e => {
    e.preventDefault();
    validateFirstName();
    validateLastName();
  };
}

所以在我的formSubmitHandler 中,我依次调用每个方法。这是错的吗?例如,他们需要async 吗?还是问题出在我的setError 函数中?我没有正确设置更新的状态吗?

当我退出errors 时,我只看到lastName

{"errors": {"lastName": "Last Name is required"}}

我可以尝试什么来解决这个问题?

【问题讨论】:

    标签: react-native react-hooks state


    【解决方案1】:

    您可以通过不同的方式来执行此操作。您也可以只批量处理来自验证器的响应并一次性设置状态。这也将减少您的应用的重新呈现。

    工作示例:https://snack.expo.dev/@tnr_c/funny-raspberries

    【讨论】:

    • 感谢您提供示例,我想我会试试这个。所以要正确理解,可以说我的表单有 10 个字段要验证,使用我当前的实现,我将渲染 10 次?而在您的示例中,我可以只重新渲染一次并且仍然验证所有字段?
    • 对 state/props 的更改将导致组件重新渲染。然而,react 对事件处理程序和批处理它们很聪明。您可以在此处找到更多信息:stackoverflow.com/a/48610973/458193。如果您将所有验证器批处理到示例中的按钮按下等事件,您可以按照@user3812411 建议的更改方式处理它,它会正常工作。
    【解决方案2】:

    这就是你的问题所在:

      {
        ...prevState.lastName,
        lastName: 'Last Name is too short',
      }
    

    您只是将姓氏(或其他函数中的名字)传递给您的新状态,因此它不再具有其他值。

    只要做:

      {
        ...prevState,
        lastName: 'Last Name is too short',
      }
    

    对于所有这些,您现在应该拥有错误状态中的所有值

    【讨论】:

    • 哦,成功了,太棒了!非常感谢...只需要弄清楚为什么现在这样有效,不太确定我是否完全理解流程
    • 所以,您正在做的是使用一个状态对象来处理所有错误。所以,对象看起来像 {error1: "", error2: "", ...}。现在,当您更新状态时,prevState 是包含所有错误的整个当前对象,因此您传递 {...prevState} 并使用 {...prevState, error1: "new value"} 替换您要更改的对象.
    • 明白了,现在更有意义了,谢谢
    • 可能需要一个单独的问题,但如果需要,我将如何从错误对象中删除密钥?
    • @Richlewis 将对象复制到一个常量中(const tmp = errors),删除 tmp.yourKey,setErrors(tmp)。因此,例如,如果您要删除 lastName,请删除 tmp.lastName 然后 setErrors(tmp)
    【解决方案3】:

    将函数按照与表单相同的顺序排列,因此在转到下一个之前先检查每个函数。

    【讨论】:

    • 谢谢@Arti,所以我会在我的formSubmitHandler 中设置这个?
    • @Richlewis useEffect 用在外面,就像一个componentDidMount函数,和其他函数分开,别忘了从react中导入useEffect!
    • @Richlewis 把这个留在这里它可能会对你有所帮助! useEffect
    • 谢谢 :-),会花一些时间阅读,确实尝试了上述选项,第一个以无限循环结束,第二个似乎没有改变任何东西.. 会继续寻找跨度>
    • 你介意把 validateFirstName();下面 validateLastName();在提交功能?如果在错误中打印 {"errors": {"firstName": "First Name is required"}} 这是因为 lastname 正在替换 useState 并且您需要添加 , 来声明而不是替换它。
    【解决方案4】:

    react 中的状态变化是异步的,所以:

    validateFirstName();
    validateLastName();
    

    你在哪里更新错误状态会导致不可预知的结果。 在反应中进行表单验证的选项很少,为了保持基本的我会开始: https://reactjs.org/docs/hooks-reference.html#usereducer

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-06
      • 2020-04-24
      • 2022-01-22
      • 1970-01-01
      相关资源
      最近更新 更多