Repository: ant-design
Issue: [Feature Request] Subscribe formValues changed by useEffect
Labels: 🗣 Discussion,Inactive

### 这个功能解决了什么问题？

希望表单字段值变化的时候, 可以使用`useEffect`来监听这个字段的值的变化, 从而可以执行一些更复杂的副作用(如最常见的重新根据表单值去调用接口等)

下面举一个具体的例子, 参考该[codesandbox](https://codesandbox.io/s/priceless-visvesvaraya-wqzv6?file=/src/App.tsx)

```tsx
import { Button, Form, Select } from "antd";
import "antd/dist/antd.css";
import React from "react";

type FormValues = { condition: string };

const mockApi = (condition: string) => {
  // call some backend api
  return new Promise<string>((resolve) => {
    setTimeout(() => {
      const data =
        {
          conditionA: "dataA",
          conditionB: "dataB"
        }[condition] || "others";
      resolve(data);
    }, 100);
  });
};
function useDataByCondition(condition: string) {
  const [data, setData] = React.useState("");
  React.useEffect(() => {
    const fetchData = async () => {
      const response = await mockApi(condition);
      setData(response);
    };
    fetchData();
  }, [condition]);
  return data;
}
export default function App() {
  const [form] = Form.useForm<FormValues>();
  const [condition, setCondition] = React.useState("conditionA");
  // want to use `useDataByCondition` hook to read data
  const data = useDataByCondition(condition);
  return (
    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
      <Form.Item label="condition" name="condition" initialValue="condition1">
        <Select<string> onChange={setCondition}>
          <Select.Option value="conditionA">conditionA</Select.Option>
          <Select.Option value="conditionB">conditionB</Select.Option>
        </Select>
      </Form.Item>

      <Form.Item label="result by condition">{data}</Form.Item>

      <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
}

```

我希望在选择完`condition`的时候, 能够重新调用接口去渲染不同的result. 然而直接使用`useEffect(() => fetchData(), [form.getFieldValue('condition')])`是行不通的, 因为当`condition`下拉重新选择以后, 并不会触发整个Form组件的渲染, 从而不会重新执行useEffect

一般来说, 我想到以下解决办法:

1. 像例子里一样, 在onChange同步表单状态到组件的state, 然后`useEffect`监听组件本地state的变化即可. 但是这样子做看起来有些冗余, 因为同步了表单的状态, 明明有表单的状态, 我为什么不能直接用呢? 而且在联动情况比较多, 业务相对比较复杂的情况下, 派生的组件本地state也会变多, 会变得比较啰嗦

2. 和1类似, 只是不同步本地表单状态, 直接在onChange的时候调用接口而不是使用用useEffect. 这样可以消除mirror的表单状态, 但会使onChange函数变得冗长

3. 拆分组件, 将此例的`result`的FormItem的内容抽象成一个组件, 使用renderProp形式的Form.Item写法, 把hooks放入组件里e.g.

```tsx
const Result = (props: {condition: string}) => {
   const data = useDataByCondition(condition)
   return <div>{data}</div> 
}

<Form.Item name='result' shouldUpdate={(prev, curr) => prev.condition !== curr.condition}>
 {
   ({. getFieldValue }) => <Result condition={getFieldValue(condition)}  />
 }
</Form.Item>
```

但是现实没有这么美好, `data`常常不会只被一个组件用到, 而且联动的关系应该在上层的组件里体现才好

4. 自己封装一下, 大体和1类似, 可以在`onValuesChange`做一些操作
但是表单项的`onChange`和on`onValuesChange`在`form.setFieldsValues`的情况下都不会触发, 让我有些纠结感觉不能覆盖到全部情况

我知道[react-hook-form有一个watch的功能](https://react-hook-form.com/api/useform/watch), 尽管文档里说:
> watch result is optimised for render phase instead of useEffect's deps, to detect value update you may want to use an external custom hook for value comparison.

我不知道具体的原因, 但是从API角度来讲, 好像是符合我预期的


### 你期望的 API 是怎样的？

综上所述, 我希望`useForm`能暴露出一个`formValues`的state, 它是一个React State, 当表单值有变化时, 可以使用 `useEffect`监听到. 并且`setFieldsValue `也能使其更新.

```jsx
const [ form, { formValues } ] = Form.useForm()
const { field } = formValues

React.useEffect(() => {
  console.log(formValues, 'formValues changed'
}, [formValues])

React.useEffect(() => {
  console.log(field, 'formValues.field changed'
}, [field])
```

### 其他

受限于知识面, 如果有其他更好的解决办法或者建议, 还请不吝赐教. Thx for the awesome UI library for community👏

<!-- generated by ant-design-issue-helper. DO NOT REMOVE -->