最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to render an element when form.isFieldsTouched() changes - Stack Overflow

programmeradmin0浏览0评论

I'm migrating ant-design to v4, and I'm not sure what is the remended way to migrate the following case.

I have a form, with an input, and a submit button. The submit button is not rendered unless form.isFieldsTouched() === true. In v3 this was not a problem to implement. Antd v4 is using hooks, and this became a problem.

Consider the following form. The submit button will not render after the input is changed. =/src/App.js

import { Form, Input } from "antd";

export default function App() {
  const [form] = Form.useForm();
  return (
    <Form form={form}>
      <Form.Item name="name">
        <Input />
      </Form.Item>
      {form.isFieldsTouched() && <button type="submit">Submit</button>}
    </Form>
  );
}

There's a "way" to make it work and render, but it feels wrong and hacky. Also Form.Item adds it's unwanted styles. =/src/App.js

import { useState } from 'react';
import { Form, Input } from "antd";

export default function App() {
  const [form] = Form.useForm();
  const [isTouched, setIsTouched] = useState(form.isFieldsTouched());
  return (
    <Form form={form}>
      <Form.Item name="name">
        <Input />
      </Form.Item>
      <Form.Item 
        shouldUpdate={() => {
          const didChange = form.isFieldsTouched() !== isTouched;
          if (didChange) {
            setIsTouched(form.isFieldsTouched());
          }
          return didChange;
        }}
      >
        {() => form.isFieldsTouched() && <button type="submit">Submit</button>}
      </Form.Item>
    </Form>
  );
}

Did you have a similar case? How did you solve it?

I'm migrating ant-design to v4, and I'm not sure what is the remended way to migrate the following case.

I have a form, with an input, and a submit button. The submit button is not rendered unless form.isFieldsTouched() === true. In v3 this was not a problem to implement. Antd v4 is using hooks, and this became a problem.

Consider the following form. The submit button will not render after the input is changed. https://codesandbox.io/s/zealous-rgb-pc7ke?file=/src/App.js

import { Form, Input } from "antd";

export default function App() {
  const [form] = Form.useForm();
  return (
    <Form form={form}>
      <Form.Item name="name">
        <Input />
      </Form.Item>
      {form.isFieldsTouched() && <button type="submit">Submit</button>}
    </Form>
  );
}

There's a "way" to make it work and render, but it feels wrong and hacky. Also Form.Item adds it's unwanted styles. https://codesandbox.io/s/delicate-browser-0y9f9?file=/src/App.js

import { useState } from 'react';
import { Form, Input } from "antd";

export default function App() {
  const [form] = Form.useForm();
  const [isTouched, setIsTouched] = useState(form.isFieldsTouched());
  return (
    <Form form={form}>
      <Form.Item name="name">
        <Input />
      </Form.Item>
      <Form.Item 
        shouldUpdate={() => {
          const didChange = form.isFieldsTouched() !== isTouched;
          if (didChange) {
            setIsTouched(form.isFieldsTouched());
          }
          return didChange;
        }}
      >
        {() => form.isFieldsTouched() && <button type="submit">Submit</button>}
      </Form.Item>
    </Form>
  );
}

Did you have a similar case? How did you solve it?

Share Improve this question asked May 7, 2021 at 10:39 Martin SkecMartin Skec 1282 silver badges9 bronze badges 3
  • 1 antd uses rc-field-form under the hood and the reason you need to resort to those kind of hacks is a poor API design of that library. It's supposed to improve render performance by bailing out from rendering everywhere but doesn't provide an API to subscribe to certain changes in form state. For me that is premature optimization as most forms don't need that degree of render performance. It does more harm than good. Just my opinion. I like to use formik which allows you to opt-in into optimizations if you really need them. – trixn Commented May 7, 2021 at 12:28
  • @trixn thanks for the explanation. Now I realize there will be similar issues for other methods like form.getFieldValue('some-field'), and working around it with hacks like above can get very plex very fast. This is quite bad DX, and I will consider migrating to another form library. – Martin Skec Commented May 7, 2021 at 13:06
  • 1 This is an issue related to your problem: github./react-ponent/field-form/issues/153. Form rendering is one of the harder things in react. I know of 3 popular form libraries for react: formik, react-final-form and react-hook-form which all have their quirks. I don't know how well they would work together with antd ponents to be honest. There may be a more elegant solution using rc-field-form but from reading the docs there is no obvious way to deal with your specific problem in a better way as far as I can tell. – trixn Commented May 7, 2021 at 13:21
Add a ment  | 

2 Answers 2

Reset to default 3

I had the similar problem and at that time I solved it like this:

import { useState } from "react";
import { Form, Input } from "antd";

export default function App() {
  const [form] = Form.useForm();
  const [isTouched, setIsTouched] = useState();

  return (
    <Form
      form={form}
      onFieldsChange={() => {
        // add your additionaly logic here
        setIsTouched(true);
      }}
    >
      <Form.Item name="name">
        <Input />
      </Form.Item>
      <Form.Item>
        {isTouched && <button type="submit">Submit</button>}
      </Form.Item>
    </Form>
  );
}

I too had a similar problem. This worked for me.

import { useState } from 'react';
import { Form, Input } from "antd";

export default function App() {
  const [form] = Form.useForm();
  return (
    <Form form={form}>
      <Form.Item name="name">
        <Input />
      </Form.Item>
      <Form.Item 
        shouldUpdate={true}
      >
        {() => form.isFieldsTouched() && <button type="submit">Submit</button>}
      </Form.Item>
    </Form>
  );
}

发布评论

评论列表(0)

  1. 暂无评论