【问题标题】:Clear sub-form values on conditional hide of nested fields在嵌套字段的条件隐藏上清除子表单值
【发布时间】:2021-11-15 02:28:32
【问题描述】:

使用 React+Formik,我想创建一个可重用的组件,我们可以使用它来有条件地显示/隐藏嵌套的子表单(任何复杂性)。

每次隐藏时,我们都希望清除这些值,以免提交这些值。

下面显示了一个名为OptionalFeature 的简单隐藏/显示组件。

const OptionalFeature = ({
  toggle,
  children
}) => {
  if (toggle) {
    return <div>{children}</div>
  } else {
    return null;
  }
}

粘贴到https://codesandbox.io/s/zkrk5yldz即可测试 但正如您在演示中看到的那样,让孩子们隐形并不能清除他们的价值观。理想情况下,每个孩子都可以定义自己的 clearValue 行为(示例非常简单,我们希望有更复杂的嵌套形式)。

通过以通用、可重用的方式扩展 OptionalFeature 类来清除全名字段的干净解决方案是什么?

我已经尝试过创建一个清理函数并从 if 块内的 OptionalFeature 调用它,但它似乎不是很惯用。

// Helper styles for demo
import "./helper.css";
import { DisplayFormikState } from "./helper";

import React from "react";
import { render } from "react-dom";
import { Formik } from "formik";

// Generic reusable component to show/hide sub-forms
const OptionalFeature = ({
  toggle,
  children
}) => {
  if (toggle) {
    return <div>{children}</div>
  } else {
    return null;
  }
}

const App = () => (
  <div className="app">
    <Formik
      initialValues={{ email: "", anonymous: false, fullname:"" }}
      onSubmit={async values => {
        await new Promise(resolve => setTimeout(resolve, 500));
        alert(JSON.stringify(values, null, 2));
      }}
    >
      {props => {
        const {
          values,
          touched,
          errors,
          isSubmitting,
          handleChange,
          handleSubmit
        } = props;
        return (
          <form onSubmit={handleSubmit}>
            <input
              id="email"
              placeholder="Enter your email"
              type="text"
              value={values.email}
              onChange={handleChange}
            />

            {/* This checkbox should show/hide next field */}
            <div style={{ display: "white-space:nowrap" }}>
              <label htmlFor="anonymous" style={{ display: "inline-block"}}>Anonymous</label>
              <input 
                id="anonymous" 
                type="checkbox" 
                name="anonymous" 
                value={values.anonymous}
                onChange={handleChange}
                style={{ display: "inline-block", width: "20%"}}
                />
            </div>


            <OptionalFeature
              toggle={!values.anonymous}
            >

              {/* Imagine this subform comes from a different file */}
              <input
                id="fullname"
                placeholder="Enter your full name"
                type="text"
                value={values.fullname}
                onChange={handleChange}
              />

            </OptionalFeature>


            <button type="submit" disabled={isSubmitting}>
              Submit
            </button>

            <DisplayFormikState {...props} />
          </form>
        );
      }}
    </Formik>
  </div>
);

render(<App />, document.getElementById("root"));

【问题讨论】:

    标签: javascript reactjs typescript forms formik


    【解决方案1】:

    这是我现有的方法,等待更好的答案:

    const OptionalFeature = ({
      toggle,
      onHide,
      children
    }) => {
      if (toggle) {
        return <div>{children}</div>
      } else {
        // useEffect needed because onHide function could trigger anything.
        // Also to avoid calling multiple times.
        useEffect(() => {
          onHide();
        }, [toggle, onHide])
        return null;
      }
    }
    

    然后稍后调用 onHide 的清理函数:

        <Formik
          initialValues={{ email: "", anonymous: false, fullname:"" }}
        ...>
           {props => {
            const {
              values,
              isSubmitting,
              handleChange,
              handleSubmit
            } = props;
    
            // to clean up all prop values inside the OptionalFeature
            const clearFullName = () => 
            {
              values.fullname = ""
            }
            return (
             //...
        
             <OptionalFeature
                  toggle={!values.anonymous}
                  onHide={clearFullName}      // using cleanup Function
                >
                  <input
                    id="fullname"
                    placeholder="Enter your full name"
                    type="text"
                    value={values.fullname}
                    onChange={handleChange}
                  />
                </OptionalFeature>
             );
        }}
         </Formik>
    

    我不喜欢这里的是,随着更多 OptionalFeatures 或更多嵌套在可选功能中的元素,for 变得更加复杂,因此很难检查嵌套可选表单中的所有字段是否都被清理.此外,useEffect 的属性似乎很难测试。

    我更喜欢某种嵌套的子表单,这样我就可以编写类似 onHide={handleReset} 的东西,并且这将只限于嵌套子表单内的字段,而无需为此定义自定义的 handleReset 函数。

    【讨论】:

      猜你喜欢
      • 2016-12-28
      • 2016-03-19
      • 2018-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多