Ant Design реагирует на событие изменения формы в form.resetFields()

#javascript #reactjs #antd

#javascript #reactjs #antd

Вопрос:

У меня есть <Form> компонент Ant Design с несколькими <Form.Items> . Одним из них является a <Select> , который зависит от нескольких других <Form.Item> состояний для изменения <Options> стиля в зависимости от комбинации выбранных значений в другом <Form.Items> . Я работаю с дополнительным объектом useState ( activeQuestions ), чтобы упростить обработку более сложных комбинаций. Моя проблема в том, что когда форма сбрасывается form.resetFormFields() или устанавливается, form.setFieldsValue() она не будет вызывать мои используемые события onChange, поскольку форма antd является неконтролируемой формой. Так что я не уверен, как подойти к этому. Существует shouldUpdate on <Form.Items> , но я не уверен, как и если это правильный подход для этой цели.

Итак, в созданном мной упрощенном примере изолированной среды при изменении всех значений <Radio> на Yes запускается событие onChange, которое проверяется, а затем некоторые параметры выбора становятся серыми. Но при использовании одной из двух кнопок сверху reset или fill это не обновит состояние.

Есть ли что-то в форме Ant Design, чего мне не хватает? Потому что это должно быть обычной задачей. Каков хороший способ решения этой проблемы?

Ссылка на изолированную среду кода с примером:

https://codesandbox.io/s/antd-form-item-based-on-other-item-forked-zofnj?file=/src/AntDFormChild.js

Что я пробовал (это вызывает бесконечный цикл)

  <Form.Item
        noStyle
        shouldUpdate={(prevValues, currentValues) => {
          console.log(prevValues.rjr01_q01, currentValues.rjr01_q01);
          return (
            prevValues.rjr01_q01 !== currentValues.rjr01_q01 amp;amp;
            prevValues.rjr02_q01 !== currentValues.rjr02_q01
          );
        }}
      >
        {({ getFieldValue }) => {
          setSelections((selections) => ({
            rjr01_q01: getFieldValue("rjr01_q01"),
            rjr02_q01: getFieldValue("rjr02_q01")
          }));

          return null;
        }}
      </Form.Item>
 

Пример

 import React, { useState, useEffect } from "react";
import { Descriptions, Form, Radio, Select, Typography } from "antd";

const { Text } = Typography;
const { Option } = Select;

const questionsData = {
  rjr01_q01: { title: "Question 1", description: "Question 1 description" },
  rjr02_q01: { title: "Question 2", description: "Question 2 description" }
};

const AntDFormChild = ({ form }) => {
  const [selections, setSelections] = useState({
    rjr01_q01: null,
    rjr02_q01: null
  });
  const [activeQuestions, setActiveQuestions] = useState([]);

  useEffect(() => {
    console.log("selections state update", selections);
    // if question 1 is yes
    if (selections.rjr01_q01 === 1 amp;amp; !activeQuestions.includes("rjr01_q01")) {
      setActiveQuestions((activeQuestions) => [
        ...activeQuestions,
        "rjr01_q01"
      ]);
    }
    // if question 1 is not yes
    if (selections.rjr01_q01 !== 1 amp;amp; activeQuestions.includes("rjr01_q01")) {
      setActiveQuestions((activeQuestions) => [
        ...activeQuestions.filter((i) => i !== "rjr01_q01")
      ]);
    }

    // if question 2 is yes
    if (selections.rjr02_q01 === 1 amp;amp; !activeQuestions.includes("rjr02_q01")) {
      setActiveQuestions((activeQuestions) => [
        ...activeQuestions,
        "rjr02_q01"
      ]);
    }
    // if question 2 is not yes
    if (selections.rjr02_q01 !== 1 amp;amp; activeQuestions.includes("rjr02_q01")) {
      setActiveQuestions((activeQuestions) => [
        ...activeQuestions.filter((i) => i !== "rjr02_q01")
      ]);
    }
  }, [selections]);

  useEffect(() => {
    console.log("activeQuestions state update", activeQuestions);
  }, [activeQuestions]);

  return (
    <>
      <Form.Item
        noStyle
        shouldUpdate={(prevValues, currentValues) => {
          console.log(prevValues.rjr01_q01, currentValues.rjr01_q01);
          return (
            prevValues.rjr01_q01 !== currentValues.rjr01_q01 amp;amp;
            prevValues.rjr02_q01 !== currentValues.rjr02_q01
          );
        }}
      >
        {({ getFieldValue }) =>
          getFieldValue("rjr01_q01") === 1 amp;amp;
          getFieldValue("rjr02_q01") === 1 ? (
            <div style={{ color: "red" }}>
              You checked all answered with yes
            </div>
          ) : null
        }
      </Form.Item>
      <Form.Item name="rjr01_q01" label="Question 1">
        <Radio.Group
          onChange={(i) => {
            setSelections((selections) => ({
              ...selections,
              rjr01_q01: i.target.value
            }));
          }}
        >
          <Radio value={1}>Yes</Radio>
          <Radio value={0}>No</Radio>
          <Radio value={2}>Unknown</Radio>
        </Radio.Group>
      </Form.Item>
      <Form.Item name="rjr02_q01" label="Question 2">
        <Radio.Group
          onChange={(i) => {
            setSelections((selections) => ({
              ...selections,
              rjr02_q01: i.target.value
            }));
          }}
        >
          <Radio value={1}>Yes</Radio>
          <Radio value={0}>No</Radio>
          <Radio value={2}>Unknown</Radio>
        </Radio.Group>
      </Form.Item>

      <Form.Item name="availableQuestions" label="Available Questions">
        <Select allowClear style={{ width: 250 }}>
          {Object.keys(questionsData).map((key, index) => (
            <Option key={key} value={key}>
              <Text
                style={{
                  color: activeQuestions.includes(key) amp;amp; "lightgrey"
                }}
              >
                {questionsData[key].title}
              </Text>
            </Option>
          ))}
        </Select>
      </Form.Item>
    </>
  );
};

export default AntDFormChild;