当调用 handleChange 中的设置状态时,需要检查 Formik 表单中的 CheckBox 两次

CheckBox inside Formik form needs to be checked twice when a set state in handleChange is called

我有一个带有一组复选框的 Formik 表单,这些复选框的行为类似于单选按钮和一个回调函数:

function handleChange(
    e: ChangeEvent<HTMLInputElement>,
    arrayHelpers: FieldArrayRenderProps
  ) {

    let us: IMUserSetting = {name:"db", value:e.target.id}
    
    let c = !(userSettings.filter(x => x.name==="db" && x.value == us.value).length>0)
    
    if (arrayHelpers.form.values.userSettings.length===0){
       arrayHelpers.push(us);
     }
      else {
      arrayHelpers.pop();
      arrayHelpers.push(us);
      }

   setChanged(c);

  /*
   if (c) {
     setTimeout(tSetChange,4000)
   } else {
     setTimeout(tUnSetChange,4000)
   }
 */

  }

当对“setChanged(c)”的调用未被注释掉时,我需要单击两次复选框以更改选择,而在第一次单击后工作正常。 我花了很多时间试图弄清楚为什么会发生这种情况,甚至尝试使用 setTimeout 来设置状态,并注意到在超时到期后,标志会恢复到第一个选中的复选框。 这是我的第一个 React 作品,可能我在状态上遗漏了一些东西。

如果您想尝试,我在 codesandbox https://codesandbox.io/s/testformiktypescript-m9uik3?file=/src/userDb.tsx 上设置了一个模拟。

有人经历过类似的事情吗?

提前谢谢你。

问题是使用状态进行跟踪isChanged:

const [changed, setChanged] = useState(false);

这是一个问题的原因是,当您调用 setChanged 时,您正在更新状态,触发重新渲染,因此意外导致 Formik 表单 currentDb 重置为初始值。你只会在第一次点击时看到这个,因为一旦 changedtrue,下次你点击复选框时再次将其设置为 true 不会导致另一个重新渲染。

您正在使用 changed 来决定是否禁用确定按钮。我建议将其更改为使用 dirty 变量找出是否从 Formik 更改了任何内容,以避免导致无意的重新渲染。

{({ isSubmitting, setSubmitting, values, setValues, dirty }) => (

这是解决方案的代码和框示例!

然后您可以根据 dirty 禁用您的按钮,如下所示:

            <Button
              disabled={isSubmitting || !dirty}