{"id":375843,"date":"2024-05-21T06:35:12","date_gmt":"2024-05-21T06:35:12","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=375843"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-05-21T06:35:12","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=375843","title":{"rendered":"<span>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0444\u043e\u0440\u043c\u044b<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u043c\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u0435(\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0435\u0439) \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u0438\u0441\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u043d\u043e. \u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u0434\u0430\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u0438 React \u0441\u043e\u043b\u0438\u0434\u0430\u0440\u043d\u044b \u0441 \u044d\u0442\u0438\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043a\u043e\u0440\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f <code>useFormStatus<\/code>, \u043d\u043e, \u043d\u0430 \u043c\u043e\u0435\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u044d\u0442\u043e\u0442 \u0445\u0443\u043a \u043b\u0438\u0448\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442 \u0436\u0438\u0437\u043d\u044c \u0432 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043a\u0435\u0439\u0441\u0430\u0445, \u043d\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445.<\/p>\n<p>\u041f\u043e\u0434 \u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438 \u043a\u0435\u0439\u0441\u0430\u043c\u0438 \u044f \u0438\u043c\u0435\u044e \u0432\u0432\u0438\u0434\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u043d\u0435 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432, \u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432 (\u0438\u043b\u0438 Map\/Set)<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443\u0436\u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u0442\u0435\u0439\u0442 \u0432\u043d\u0435 \u0438\u043d\u043f\u0443\u0442\u0430\/\u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u043f\u043e\u043b\u0435 \u0438\u043b\u0438 \u0440\u0435\u0441\u0435\u0442\u043d\u0443\u0442\u044c \u0432\u0441\u044e \u0444\u043e\u0440\u043c\u0443, \u0442.\u0435. \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 API, \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0442\u0430\u0449\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0438\u043d\u043f\u0443\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u0430\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0444\u043e\u0440\u043c\u044b \u0438\u043b\u0438 \u043e\u0434\u043d\u043e \u043f\u043e\u043b\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0438\u043b\u0438 \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043b\u043e\u0433\u0438\u043d \u0441\u0432\u043e\u0431\u043e\u0434\u0435\u043d)<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0441 \u0444\u043e\u0440\u043c\u043e\u0439 \u0438\u043b\u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 (\u044d\u0442\u043e \u043a\u0430\u043a \u0440\u0430\u0437 \u043c\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439).<\/p>\n<p>\u042f \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u043c\u043d\u043e\u0433\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043c\u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u0438\u0441\u044c <code>react-hook-form<\/code> \u0438 <code>rc-field-form<\/code> (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 <code>antd<\/code>). <code>react-hook-form<\/code> \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043c\u043d\u0435 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438, \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0443\u0447\u0443 \u0432\u0441\u0435\u0433\u043e \u0438 \u043b\u0435\u0437\u0442\u044c \u0432 \u0434\u043e\u043a\u0438 \u0432 \u043b\u044e\u0431\u043e\u0439 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043d\u043e \u0437\u0430\u0442\u043e \u043e\u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u0433\u0438\u0431\u043a\u0430\u044f. \u0410 <code>rc-field-form<\/code> \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u0432\u0435\u0441\u0438\u0442 \u0438 \u043f\u043b\u043e\u0445\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430, \u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0438 \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438. \u042f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e.<\/p>\n<p>\u0412 \u043c\u043e\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ol>\n<li>\n<p>\u0414\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0430, \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 \u043e\u0434\u043d\u043e\u043c compound component. <\/p>\n<\/li>\n<li>\n<p>\u0422\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0432\u0441\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e. \u0424\u043e\u0440\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439, \u0442\u0438\u043f\u044b \u0432 \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0430\u0445 \u0438 \u0442.\u0434.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0444\u043e\u0440\u043c\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>useWatch<\/code> \u0445\u0443\u043a\u0430<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0442\u0435\u0439\u0442\u043e\u043c \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>useField<\/code> \u0445\u0443\u043a\u0430<\/p>\n<\/li>\n<li>\n<p>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0439, \u043a\u0430\u043a \u0432 <code>rc-field-form<\/code><\/p>\n<\/li>\n<li>\n<p>\u041d\u0438\u043a\u0430\u043a\u043e\u0433\u043e CSS, \u043c\u0438\u043d\u0438\u043c\u0443\u043c HTML, <code>FormItem<\/code> \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e <strong>HOC<\/strong> \u043d\u0430\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u043e\u0431\u043d\u044b\u0439 API \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u043b\u0435\u043c, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u043c\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u043c (\u0441\u0432\u043e\u0439 <code>useFieldArray<\/code> \u0438\u0437  react-hook-form)<\/p>\n<\/li>\n<\/ol>\n<p>API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0445\u043e\u0442\u0435\u043b \u0432\u0438\u0434\u0435\u0442\u044c:<\/p>\n<pre><code class=\"typescript\">\/\/ \u0444\u043e\u0440\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u0434\u0435 \u0443\u0433\u043e\u0434\u043d\u043e \/\/ \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043b\u0435\u0436\u0438\u0442 \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0435 export const MyForm = createForm({   name: '',   age: 0, })  const MyComponent = () => {   const name = MyForm.useWatch('name'); \/\/ \u0443 name \u0442\u0438\u043f string   const [age, setAge] = MyForm.useField('age'); \/\/ \u0443 age \u0442\u0438\u043f number, setAge \u0438\u043c\u0435\u0435\u0442 \u0442\u0430\u043a\u0443\u044e \u0436\u0435 \u0430\u043f\u0438\u0448\u043a\u0443, \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f useState   const nameValidationErrors = MyForm.useFieldError('name'); \/\/ \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u0432\u0441\u0435 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e    const {     setFieldValue,     setFieldsValue,     getState,     resetFields,     submit,     validateField,     validateFields   } = MyForm.formApi; \/\/ \u0432\u043d\u0443\u0442\u0440\u0438 formApi \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0444\u043e\u0440\u043c\u043e\u0439    return (     &lt;MyForm onFinish={(state) => {       \/\/ state \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d       alert(JSON.stringify(state, undefined, 2));     }}>       &lt;MyForm.Item         name=\"name\" \/\/ \u0414\u043b\u044f name \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 autocomplete         label=\"Name\"         onChange={value => {           console.log(value) \/\/ value \u0438\u043c\u0435\u0442 \u0442\u0438\u043f string         }}         rules={[           {             required: true,             message: 'Name is required',             validateTrigger: ['onFinish']           },           {            validator: async (name) => {              await validateName(name) \/\/ \u0435\u0441\u0442\u044c promise based \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438            },            message: 'Name is invalid'           }         ]}       >         {({ value, onChange }) => \/\/ value \u0438 onChange \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b, \u0442\u0443\u0442 value - string           &lt;input value={value} onChange={e => onChange(e.target.value)} \/>         }       &lt;\/MyForm.Item>       &lt;MyForm.Item name=\"age\">         {({ value, onChange }) => \/\/ \u0430 \u0442\u0443\u0442 value - number           &lt;input type=\"number\" value={value} onChange={(e) => onChange(+e.target.value)} \/>         }       &lt;\/MyForm.Item>       &lt;button type=\"submit\">         Submit button       &lt;\/button>     &lt;\/MyForm>   ) }<\/code><\/pre>\n<p>\u041d\u0435 \u0443\u0432\u0435\u0440\u0435\u043d, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u043c\u0435\u0441\u0442\u043d\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0430\u043c\u044b\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f.<\/p>\n<h2>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0444\u043e\u0440\u043c\u044b<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0441\u0442\u0435\u0439\u0442 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430\u043c \u0432\u0440\u043e\u0434\u0435 redux, \u0442\u043e \u043d\u0435 \u0442\u0430\u043a \u0443\u0436 \u043c\u043d\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e (\u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c):<\/p>\n<p>1) \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0442\u0435\u0439\u0442 \u0444\u043e\u0440\u043c\u044b \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0435\u0439\u0442\u043e\u043c \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430(\u0432 \u0432\u0438\u0434\u0435 Map\/\u043e\u0431\u044a\u0435\u043a\u0442). \u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 &#8212; \u0440\u0435\u0440\u0435\u043d\u0434\u0435\u0440 \u0432\u0441\u0435\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0444\u043e\u0440\u043c\u044b \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u0442\u0435\u0439\u0442\u0430. \u0422\u0430\u043a \u0436\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c API \u0444\u043e\u0440\u043c\u044b \u0432\u043d\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u0447\u0442\u043e \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f. \u0410 \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u044f \u043d\u0435 \u0445\u043e\u0442\u0435\u043b.<\/p>\n<p>2) \u0414\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b &#8212; \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0442\u0435\u0439\u0442 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0438 <code>Form.Item<\/code> \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>useImperativeHandle<\/code> \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0441\u0442\u0435\u0439\u0442\u043e\u043c  \u0438\u0437\u0432\u043d\u0435. \u041c\u043d\u0435 \u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0442\u0430\u043a \u0436\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 <code>Form.Item<\/code>, \u0430 \u0435\u0449\u0435 \u0436\u043e\u043d\u0433\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c ref-\u0430\u043c\u0438.<\/p>\n<p>3) \u0412\u044b\u043d\u0435\u0441\u0442\u0438 \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0444\u043e\u0440\u043c\u043e\u0439 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 <code>useRef<\/code> \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u0430 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0435\u0439\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 +  <code>useSyncExternalStore<\/code> \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044f. \u0418\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u0432 \u0438\u0442\u043e\u0433\u0435, \u043e\u043d \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043c\u043d\u0435 \u0441\u0430\u043c\u044b\u043c \u0433\u0438\u0431\u043a\u0438\u043c.<\/p>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043d\u0430 \u0441\u0442\u0435\u0439\u0442 \u043f\u043e\u043b\u044f \u0444\u043e\u0440\u043c\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"typescript\">export class FormApi&lt;State extends Record&lt;string, unknown>, Field extends GetFields&lt;State> = GetFields&lt;State>> {   private state: State   private subscribers: Map&lt;Field, FieldOnChangeCb&lt;State[Field]>[]>;    constructor(state: State) {     this.state = state;     this.subscribers = new Map();   }    getState() {     return this.state   }    onFieldChange&lt;F extends Field>(field: F, cb: FieldOnChangeCb&lt;State[F]>) {     const currentSubscribers = this.subscribers.get(field) || [];     this.subscribers.set(field, currentSubscribers.concat(cb as FieldOnChangeCb&lt;State[Field]>));      return () => { \/\/ unsubscribe       this.subscribers.set(field, this.subscribers.get(field)?.filter(i => i !== cb) || []);     }   }    private triggerFieldUpdate&lt;F extends Field, V extends State[F]>(field: F, value: V) {     this.subscribers.get(field)?.forEach(cb => cb(value));   }    setFieldsValue(update: Partial&lt;State>) {     this.state = {       ...this.state,       ...update,     }     for (const field in update) {       this.triggerFieldUpdate(field as Field, update[field] as State[Field])     }   }    setFieldValue&lt;F extends Field>(field: F, value: FieldUpdate&lt;State[F]>) {     if (typeof value === 'function') {       this.state[field] = (value as FieldsUpdateCb&lt;State[typeof field]>)(this.state[field]);     } else {       this.state[field as Field] = value     }     this.triggerFieldUpdate(field, this.state[field])   }    getFieldValue&lt;F extends Field>(field: F) {     return this.getState()[field];   } }  export const useWatch = &lt;   Form extends FormApi&lt;any>,   Types extends FormApiGenericTypes&lt;Form>,   State extends Types['state'],   Field extends Types['field'] >(form: Form, field: Field) => {   const value = useSyncExternalStore&lt;State[Field]>(     cb => form.onFieldChange(field, cb),     () => form.getFieldValue(field),     () => form.getFieldValue(field),   )    return value; }<\/code><\/pre>\n<h2>FormItem<\/h2>\n<p>\u041e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u0441\u0442\u0430\u043b API \u0434\u043b\u044f <code>FormItem<\/code>. \u041c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0442\u0430\u043a\u0443\u044e \u0436\u0435  \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0443, \u043a\u0430\u043a \u0432 <code>rc-field-form<\/code>, \u0442.\u0435. \u043d\u0435\u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"typescript\">&lt;FormItem name=\"username\">   &lt;input placeholder=\"Username\" \/> &lt;\/FormItem><\/code><\/pre>\n<p>\u043d\u043e \u0432 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>\u0412 \u0438\u0434\u0435\u0430\u043b\u0435 \u044f \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u043b \u0432 FormItem \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>normalize<\/code> \u0438 <code>getValueFromEvent<\/code> , \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c <code>value<\/code> \u043a \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443 \u0442\u0438\u043f\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0443 <code>children<\/code> \u043f\u043e\u043b\u0435\u0439 <code>value<\/code> \u0438 <code>onChange<\/code>, \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0438\u0437 \u043d\u0438\u0445 \u0442\u0438\u043f\u044b \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432  <code>normalize<\/code> \u0438 <code>getValueFromEvent<\/code> .<\/p>\n<p>\u041a \u043c\u043e\u0435\u043c\u0443 \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e JSX \u0443\u0431\u0438\u0432\u0430\u0435\u0442 \u0442\u0438\u043f\u044b \u0438 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u043f\u0441\u044b \u0438\u0437 <code>children<\/code>.  \u0421\u0430\u043c\u043e\u0435 \u0437\u0430\u0431\u0430\u0432\u043d\u043e\u0435 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 &#8212; <code>React.createElement<\/code> \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<pre><code class=\"typescript\"> type ReturnElementProps&lt;El> = El extends React.ReactElement&lt;infer P> ? P : never  type FormItemProps&lt;   Val,   El extends React.ReactElement,   Props extends ReturnElementProps&lt;El>,   ElVal = Props['value'] > = {   value: Val,   getValueFromEvent: (...args: Parameters&lt;Props['onChange']>) => Val,   normalize: (value: Val) => ElVal,   children: El }  const FormItem = &lt;Val, El extends React.ReactElement, Props extends ReturnElementProps&lt;El>>(props: FormItemProps&lt;Val, El, Props>) => {   return &lt;>{props.children}&lt;\/> }  \/\/ \u0422\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 const Test = &lt;FormItem   value={0}   getValueFromEvent={(event) => Number(event.target.value)}   normalize={(value) => String(value)} >   {React.createElement('input')} &lt;\/FormItem>  \/\/ \u0410 \u0442\u0430\u043a\u043e\u0439 - \u0443\u0436\u0435 \u043d\u0435\u0442 :( const Test2 = &lt;FormItem   value={0}    getValueFromEvent={(event) => Number(event.target.value)} \/\/ event \u0442\u0443\u0442 - unknown   normalize={(value) => String(value)} >  &lt;input \/> &lt;\/FormItem> <\/code><\/pre>\n<p>\u0425\u043e\u0442\u044f \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b &#8212; JSX \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0441\u0430\u0445\u0430\u0440\u043e\u043c \u043d\u0430\u0434 <code>createElement<\/code> \u0438 \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u0437\u0430\u0438\u043c\u043e\u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u043c\u0438. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u043d\u0435\u043a\u0438\u0439 \u0431\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u0433\u0434\u0430-\u043d\u0438\u0431\u0443\u0434\u044c \u0438\u0441\u043f\u0440\u0430\u0432\u044f\u0442. \u041d\u043e \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u044f \u043d\u0435 \u043d\u0430\u0448\u0435\u043b \u043d\u0438\u0447\u0435\u0433\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c render function \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 children:<\/p>\n<pre><code class=\"typescript\">&lt;FormItem name=\"myField\">   {({ value, onChange }) => &lt;input value={String(value)} onChange={e => onChange(Number(e.target.value))} \/>} &lt;\/FormItem><\/code><\/pre>\n<h2>\u0422\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0432\u044b\u0448\u0435, \u0441 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u0441\u0435 \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e. \u042f \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u043e\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u0431\u044b\u043b\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e, \u0430 \u044d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u0444\u0438\u0448\u0435\u043a \u0442\u0430\u0439\u043f\u0441\u043a\u0440\u0438\u043f\u0442\u0430.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u043c\u0435\u0442\u043e\u0434 <code>onFieldChange<\/code> \u0438\u043b\u0438 \u0445\u0443\u043a <code>useWatch<\/code> \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u043b\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u0435\u0439 \u0444\u043e\u0440\u043c\u044b.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0442\u0438\u043f<\/p>\n<pre><code class=\"typescript\">type Test = {   age: number   name: string }<\/code><\/pre>\n<p>\u0438 \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c <code>'age' | 'name'<\/code> &#8212; \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>keyof<\/code>, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u0435\u043d <code>Extract<\/code>, \u0447\u0442\u043e\u0431\u044b \u0442\u043e\u0447\u043d\u043e \u0431\u044b\u0442\u044c \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e \u043c\u044b \u0434\u043e\u0441\u0442\u0430\u0435\u043c <code>string<\/code>.<\/p>\n<pre><code class=\"typescript\">type GetFields&lt;T extends Record&lt;string, unknown>> = Extract&lt;keyof T, string>  type TestFields = GetFields&lt;Test> \/\/ 'age' | 'name'<\/code><\/pre>\n<p>\u0414\u0430\u0436\u0435 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e <code>State<\/code> \u0443 \u043c\u0435\u043d\u044f \u0437\u0430\u0432\u044f\u0437\u0430\u043d \u043d\u0430 \u0442\u0438\u043f <code>Record&lt;string, unknown><\/code>, <code>keyof State<\/code> \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0440\u0443\u0433\u0430\u043b\u0441\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043a\u043b\u044e\u0447\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>symbol<\/code>. \u0421 <code>Extract<\/code> \u0436\u0435 \u0442\u0430\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c.<\/p>\n<pre><code class=\"typescript\">\/\/ \u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432 setFieldValue \u0438 getFieldValue export class FormApi&lt;State extends Record&lt;string, unknown>, Field extends GetFields&lt;State> = GetFields&lt;State>> {   private state: State    constructor(state: State) {     this.state = state;   }    setFieldValue&lt;F extends Field>(field: F, value: State[F]) {     this.state[field] = value;   }    getFieldValue&lt;F extends Field>(field: F) {     return this.state[field];   } }  \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 const myForm = new FormApi({ a: '', b: 0 });  const a = myForm.getFieldValue('a') \/\/ string const b = myForm.getFieldValue('b') \/\/ number const c = myForm.getFieldValue('c') \/\/ Argument of type '\"c\"' is not assignable to parameter of type '\"a\" | \"b\"'<\/code><\/pre>\n<p>\u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435 \u0434\u0435\u043b\u0430 \u043e\u0431\u0441\u0442\u043e\u044f\u043b\u0438 \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0438\u0437 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u0444\u043e\u0440\u043c\u044b. \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0448\u0435\u043b <code>infer<\/code>, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0447\u0435\u043c\u0443 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0442\u0438\u043f \u0441\u0442\u0435\u0439\u0442\u0430 \u0438 \u0442\u0438\u043f \u043f\u043e\u043b\u0435\u0439 \u0438\u0437 <code>FormApi<\/code>.<\/p>\n<pre><code class=\"typescript\">export type FormApiGenericTypes&lt;T> = T extends FormApi&lt;infer S, infer F>   ? { formApi: T, state: S, field: F } :  never  export const useWatch = &lt;   Form extends FormApi&lt;any>,   Types extends FormApiGenericTypes&lt;Form>,   State extends Types['state'],   Field extends Types['field'] >(form: Form, field: Field) => {  }  \/\/ \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:  const form = new FormApi({ age: 0, name: '' }); const age = useWatch(form, 'age');<\/code><\/pre>\n<p>\u0416\u0430\u043b\u044c, \u0447\u0442\u043e \u0432 ts \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432 \u043d\u0435\u043b\u044c\u0437\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0437\u0430\u0446\u0438\u044e&#8230; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u044b\u043b\u043e \u0431\u044b \u043a\u0441\u0442\u0430\u0442\u0438. \u0411\u0443\u0434\u0443 \u0440\u0430\u0434, \u0435\u0441\u043b\u0438 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u044f \u0441\u0435\u0431\u044f \u043f\u0435\u0440\u0435\u043c\u0443\u0434\u0440\u0438\u043b \u0438 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0438\u0437\u044f\u0449\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c. \u041d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0442\u0430\u043a.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044f \u043d\u0430\u0447\u0430\u043b \u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e API (\u0438 hook) \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438, \u044f \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u043a\u043e\u043c\u043f\u043b\u0438\u0442 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u044f, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438. <\/p>\n<p>\u041e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e ts \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044f \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u0443\u0441\u043b\u043e\u0432\u0438\u044e, \u0442.\u0435. \u0432\u043f\u043e\u043b\u043d\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c <code>pickBy<\/code> \u0438\u0437 <code>lodash<\/code>, \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432. <\/p>\n<pre><code class=\"typescript\">export type GetFields&lt;T extends Record&lt;string, unknown>> = Extract&lt;keyof T, string>  export type PickBy&lt;Obj extends Record&lt;string, unknown>, Predicate> = {   [Property in keyof Obj as Obj[Property] extends Predicate ? Property : never]: Obj[Property] }  export type ArrayOnlyFields&lt; Obj extends Record&lt;string, unknown>, > = GetFields&lt;PickBy&lt;Obj, unknown[]>>  type Test = {   num: number   str: string   strArr: string[]   numArr: number[] }  type TestFields = ArrayOnlyFields&lt;Test> \/\/ 'strArr' | 'numArr' <\/code><\/pre>\n<p>\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0432 <code>Extract<\/code> \u0438 <code>PickBy<\/code> \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043a\u043e\u043c\u043f\u043b\u0438\u0442\u0430 \u0432 <code>useArrayField<\/code> \u0438 <code>Form.ArrayItem<\/code> \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438. \u0414\u0443\u043c\u0430\u044e, \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u043d\u043e \u0438 \u0432 \u043a\u0443\u0447\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u0435\u0439\u0441\u043e\u0432.<\/p>\n<h2>Compound component<\/h2>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0441\u0443\u043d\u0443\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u0445\u0443\u043a\u0438 \u0432 \u043e\u0434\u0438\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u043f\u043e\u0434\u0445\u043e\u0434 <strong>compound component<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a. \u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0441\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u0443 \u043c\u0435\u043d\u044f \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0432\u0435\u0437\u0434\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u043a\u0438.<\/p>\n<p>\u0411\u0435\u0437 \u0433\u0435\u043d\u0435\u0440\u0438\u043a\u043e\u0432 \u0432\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e &#8212; <\/p>\n<pre><code class=\"typescript\">const CompoundForm = Form as typeof Form &amp; {   Item: typeof FormItem,   ArrayItem: typeof FormArrayItem,   formApi: typeof FormApi,   \/\/ \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435 }<\/code><\/pre>\n<p>\u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c HOC\/HOF \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432\/\u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0432 \u0442\u0443\u0434\u0430 <code>form<\/code> \u0438 \u043f\u0440\u043e\u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0432 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"typescript\">export const createForm = &lt;State extends Record&lt;string, unknown>>(initialState: State) => {   const form = new FormApi(initialState);    type Types = FormApiGenericTypes&lt;typeof form>;    type ArrayFields = ArrayOnlyFields&lt;Types['state']>;    const FormComponent = (props: FormProps&lt;Types['state'], FormApi&lt;Types['state']>>) =>     &lt;Form form={form} {...props} \/>    const FormItemComponent = &lt;T extends Types['field']>(props: FormItemProps&lt;T, Types['state'][T]>) => &lt;FormItem {...props} \/>    const ArrayItemComponent = &lt;T extends ArrayFields>(props: FormArrayItemProps&lt;T, ArrayOnly&lt;Types['state'][T]>>) => &lt;FormArrayItem {...props} \/>    const useWatchHook = &lt;T extends Types['field']>(field: T) => useWatch(form, field)    const useFieldHook = &lt;T extends Types['field']>(field: T) => useField(form, field)    const useFieldErrorHook = &lt;T extends Types['field']>(field: T) => useFieldError(form, field)    const useArrayFieldHook = &lt;T extends ArrayFields>(field: T, rules?: ValidationRule&lt;Types['state'][T]>[]) => useArrayField(form, field, rules)    const CompoundForm = FormComponent as typeof FormComponent &amp; {     Item: typeof FormItemComponent     useWatch: typeof useWatchHook,     useField: typeof useFieldHook,     ArrayItem: typeof ArrayItemComponent,     formApi: typeof form,     useFieldError: typeof useFieldErrorHook,     useArrayField: typeof useArrayFieldHook,   }    CompoundForm.formApi = form;   CompoundForm.Item = FormItemComponent;   CompoundForm.ArrayItem = ArrayItemComponent;   CompoundForm.useWatch = useWatchHook;   CompoundForm.useField = useFieldHook;   CompoundForm.useArrayField = useArrayFieldHook;   CompoundForm.useFieldError = useFieldErrorHook;    return CompoundForm }<\/code><\/pre>\n<p>\u041c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u043a\u0435\u0439\u0441\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u0443\u043c\u0435\u0441\u0442\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u043b\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. <\/p>\n<h2>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f<\/h2>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0432\u0441\u0435, \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0438\u0437\u043b\u0438\u0448\u043d\u0438\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 schema validator-\u043e\u0432 \u0432\u0440\u043e\u0434\u0435 zod \u0438\u043b\u0438 yup. \u0412 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0436\u0438\u0437\u043d\u044c \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 required, min\/max. \u041e\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f. \u042d\u0442\u043e \u0441\u043f\u043e\u0440\u043d\u044b\u0439 \u0448\u0430\u0433, \u043d\u043e \u043c\u043d\u0435 \u043d\u0443\u0436\u043d\u0430 \u0431\u044b\u043b\u0430 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438, \u0447\u0435\u0433\u043e \u043d\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043d\u0435 \u0434\u0430\u0435\u0442.<\/p>\n<p>\u042f \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"typescript\">const rules = [   {     \/\/ if field value is undefined     required: true,     message: \"Field is required\",   },   {     \/\/ if value &lt; 18     min: 18,     type: \"number\",     message: \"some message\",   },   {     \/\/ if String(value).length > 100     max: 100,     type: \"string\",     message: \"some error\",   },   {     \/\/ if myPattern.test(value) === false     type: \"regexp\",     pattern: myPattern,   },   {     \/\/ If value is not an email address     type: \"email\",   },   {     \/\/ if myValidator return Promise.reject     validator: myValidator,     message: \"some error\",   }, ];<\/code><\/pre>\n<p>\u042f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u0440\u043e\u043c\u0438\u0441\u0430\u0445, \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u0437\u044f\u0449\u043d\u043e:<\/p>\n<pre><code class=\"typescript\">export const checkMin = async &lt;T>(value: T, rule: ValidationRule&lt;T>) => {   if (!('min' in rule)) {     return   }   if (typeof rule.min !== 'number') {     return;   }   if (Array.isArray(value) &amp;&amp; value.length &lt; rule.min) {     return Promise.reject(rule.message);   }   if (rule.type === 'number' &amp;&amp; Number(value) &lt; rule.min) {     return Promise.reject(rule.message);   }   if (rule.type === 'string' &amp;&amp; String(value).length &lt; rule.min) {     return Promise.reject(rule.message);   } };  export const checkMax = async &lt;T>(value: T, rule: ValidationRule&lt;T>) => {   if (!('max' in rule)) {     return   }   if (typeof rule.max !== 'number') {     return;   }   if (Array.isArray(value) &amp;&amp; value.length > rule.max) {     return Promise.reject(rule.message);   }   if (rule.type === 'number' &amp;&amp; Number(value) > rule.max) {     return Promise.reject(rule.message);   }   if (rule.type === 'string' &amp;&amp; String(value).length > rule.max) {     return Promise.reject(rule.message);   } };  export const checkRequired = async &lt;T>(value: T, rule: ValidationRule&lt;T>) => {   if (typeof value === 'undefined') {     return Promise.reject(rule.message);   }   if (typeof value === 'number' &amp;&amp; value === 0) {     return;   }   if (Array.isArray(value) &amp;&amp; value.length === 0) {     return Promise.reject(rule.message);   }   if (!value &amp;&amp; typeof value !== 'boolean') {     return Promise.reject(rule.message);   } };  export const checkPattern = async &lt;T>(value: T, rule: ValidationRule&lt;T>) => {   if ('pattern' in rule &amp;&amp; typeof value === 'string' &amp;&amp; !rule.pattern.test(value)) {     return Promise.reject(rule.message || 'Invalid format');   }   return };   export const getValidationErrors = async &lt;Value,>(   value: Value,   rules: (ValidationRule&lt;Value> &amp; { validateTrigger: ValidateTrigger[] })[],   trigger?: ValidateTrigger ) => {   const result = [] as {     rule: typeof rules[number],     validator: Validator&lt;Value>   }[];    for (const rule of rules) {     if (trigger &amp;&amp; !rule.validateTrigger.includes(trigger)) {       continue     }     if (rule.required) {       result.push({         rule,         validator: checkRequired,       });     }     if ('min' in rule) {       result.push({         rule,         validator: checkMin,       });     }     if ('max' in rule) {       result.push({         rule,         validator: checkMax,       });     }     if (rule.type === 'regexp' &amp;&amp; 'pattern' in rule) {       result.push({         rule,         validator: checkPattern,       });     }     if (rule.type === 'email') {       result.push({         rule: {           ...rule,           type: 'regexp',           pattern: emailRegex,         },         validator: checkPattern,       })     }     if ('validator' in rule) {       result.push({         rule,         validator: rule.validator,       });     }   }    const settledPromises = await Promise.allSettled(     result.map(({ validator, rule }) =>       validator(value, rule)         .catch(error => {           const errorText = rule.message || String(error);           return Promise.reject&lt;ValidationError>({             errorText,             value,             rule,           })         })     ));    return filterOnlyRejectedPromises&lt;ValidationError&lt;Value>>(settledPromises).map(i => i.reason); }<\/code><\/pre>\n<h2>\u0427\u0442\u043e \u0432 \u0438\u0442\u043e\u0433\u0435<\/h2>\n<p>\u0422\u043e, \u0447\u0442\u043e \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u043e\u0441\u044c, \u043a\u0430\u043a \u0441\u043f\u043e\u0440\u0442\u0438\u0432\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0435\u0441 &#8212; \u0441\u043c\u043e\u0433\u0443 \u043b\u0438 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043a\u0440\u043e\u0435\u0442 \u0432\u0441\u0435 \u043c\u043e\u0438 \u0445\u043e\u0442\u0435\u043b\u043a\u0438, \u0432\u044b\u043b\u0438\u043b\u043e\u0441\u044c \u0432 \u043d\u0435\u043f\u043b\u043e\u0445\u0443\u044e(\u043d\u0430\u0434\u0435\u044e\u0441\u044c) \u043b\u0438\u0431\u0443, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043b\u0438\u0447\u043d\u043e \u043c\u043d\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f. \u0412 \u0446\u0435\u043b\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0444\u043e\u0440\u043c\u044b \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u043c \u043d\u0430 pet-project &#8212; \u044f \u0443\u0437\u043d\u0430\u043b \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u0448\u0442\u0443\u043a, \u043f\u043e\u043a\u0430 \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u043b \u044d\u0442\u043e\u0442 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434.<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0443-\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439, \u043a\u0430\u043a \u0438 \u0441\u0430\u043c\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430. \u042f \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438(\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043a\u0440\u0438\u0442\u0438\u043a\u0435 \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c), \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0434\u043e\u0432\u0435\u0441\u0442\u0438 \u044d\u0442\u0443 \u043b\u0438\u0431\u0443 \u0434\u043e \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043d\u0434\u0438\u0446\u0438\u0438. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432\u044b\u043b\u043e\u0436\u0435\u043d \u043d\u0430 <a href=\"https:\/\/github.com\/deadrime\/react-any-shape-form\" rel=\"noopener noreferrer nofollow\">github<\/a>, \u0434\u043e\u043a\u0438 \u043b\u0435\u0436\u0430\u0442 <a href=\"https:\/\/react-any-shape-form.vercel.app\/\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>npm i react-any-shape-form<\/code> . \u0412\u0435\u0441\u0438\u0442 \u0432\u0441\u0435\u0433\u043e ~9.1kb\/3kb gzip, \u0435\u0441\u043b\u0438 \u0432\u0435\u0440\u0438\u0442\u044c bundlephobia.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/813551\/\"> https:\/\/habr.com\/ru\/articles\/813551\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u043c\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u0435(\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0435\u0439) \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u0438\u0441\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u043d\u043e. \u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u0434\u0430\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u0438 React \u0441\u043e\u043b\u0438\u0434\u0430\u0440\u043d\u044b \u0441 \u044d\u0442\u0438\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043a\u043e\u0440\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f <code>useFormStatus<\/code>, \u043d\u043e, \u043d\u0430 \u043c\u043e\u0435\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u044d\u0442\u043e\u0442 \u0445\u0443\u043a \u043b\u0438\u0448\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442 \u0436\u0438\u0437\u043d\u044c \u0432 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043a\u0435\u0439\u0441\u0430\u0445, \u043d\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445.<\/p>\n<p>\u041f\u043e\u0434 \u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438 \u043a\u0435\u0439\u0441\u0430\u043c\u0438 \u044f \u0438\u043c\u0435\u044e \u0432\u0432\u0438\u0434\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u043d\u0435 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432, \u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432 (\u0438\u043b\u0438 Map\/Set)<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443\u0436\u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u0442\u0435\u0439\u0442 \u0432\u043d\u0435 \u0438\u043d\u043f\u0443\u0442\u0430\/\u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u043f\u043e\u043b\u0435 \u0438\u043b\u0438 \u0440\u0435\u0441\u0435\u0442\u043d\u0443\u0442\u044c \u0432\u0441\u044e \u0444\u043e\u0440\u043c\u0443, \u0442.\u0435. \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 API, \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0442\u0430\u0449\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0438\u043d\u043f\u0443\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u0430\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0444\u043e\u0440\u043c\u044b \u0438\u043b\u0438 \u043e\u0434\u043d\u043e \u043f\u043e\u043b\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0438\u043b\u0438 \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043b\u043e\u0433\u0438\u043d \u0441\u0432\u043e\u0431\u043e\u0434\u0435\u043d)<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0441 \u0444\u043e\u0440\u043c\u043e\u0439 \u0438\u043b\u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 (\u044d\u0442\u043e \u043a\u0430\u043a \u0440\u0430\u0437 \u043c\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439).<\/p>\n<p>\u042f \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u043c\u043d\u043e\u0433\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043c\u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u0438\u0441\u044c <code>react-hook-form<\/code> \u0438 <code>rc-field-form<\/code> (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 <code>antd<\/code>). <code>react-hook-form<\/code> \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043c\u043d\u0435 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438, \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0443\u0447\u0443 \u0432\u0441\u0435\u0433\u043e \u0438 \u043b\u0435\u0437\u0442\u044c \u0432 \u0434\u043e\u043a\u0438 \u0432 \u043b\u044e\u0431\u043e\u0439 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043d\u043e \u0437\u0430\u0442\u043e \u043e\u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u0433\u0438\u0431\u043a\u0430\u044f. \u0410 <code>rc-field-form<\/code> \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u0432\u0435\u0441\u0438\u0442 \u0438 \u043f\u043b\u043e\u0445\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430, \u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0438 \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438. \u042f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e.<\/p>\n<p>\u0412 \u043c\u043e\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ol>\n<li>\n<p>\u0414\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0430, \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 \u043e\u0434\u043d\u043e\u043c compound component. <\/p>\n<\/li>\n<li>\n<p>\u0422\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0432\u0441\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e. \u0424\u043e\u0440\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439, \u0442\u0438\u043f\u044b \u0432 \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0430\u0445 \u0438 \u0442.\u0434.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0444\u043e\u0440\u043c\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>useWatch<\/code> \u0445\u0443\u043a\u0430<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0442\u0435\u0439\u0442\u043e\u043c \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>useField<\/code> \u0445\u0443\u043a\u0430<\/p>\n<\/li>\n<li>\n<p>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0439, \u043a\u0430\u043a \u0432 <code>rc-field-form<\/code><\/p>\n<\/li>\n<li>\n<p>\u041d\u0438\u043a\u0430\u043a\u043e\u0433\u043e CSS, \u043c\u0438\u043d\u0438\u043c\u0443\u043c HTML, <code>FormItem<\/code> \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e <strong>HOC<\/strong> \u043d\u0430\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u043e\u0431\u043d\u044b\u0439 API \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u043b\u0435\u043c, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u043c\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u043c (\u0441\u0432\u043e\u0439 <code>useFieldArray<\/code> \u0438\u0437  react-hook-form)<\/p>\n<\/li>\n<\/ol>\n<p>API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0445\u043e\u0442\u0435\u043b \u0432\u0438\u0434\u0435\u0442\u044c:<\/p>\n<pre><code class=\"typescript\">\/\/ \u0444\u043e\u0440\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u0434\u0435 \u0443\u0433\u043e\u0434\u043d\u043e \/\/ \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043b\u0435\u0436\u0438\u0442 \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0435 export const MyForm = createForm({   name: '',   age: 0, })  const MyComponent = () => {   const name = MyForm.useWatch('name'); \/\/ \u0443 name \u0442\u0438\u043f string   const [age, setAge] = MyForm.useField('age'); \/\/ \u0443 age \u0442\u0438\u043f number, setAge \u0438\u043c\u0435\u0435\u0442 \u0442\u0430\u043a\u0443\u044e \u0436\u0435 \u0430\u043f\u0438\u0448\u043a\u0443, \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f useState   const nameValidationErrors = MyForm.useFieldError('name'); \/\/ \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u0432\u0441\u0435 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e    const {     setFieldValue,     setFieldsValue,     getState,     resetFields,     submit,     validateField,     validateFields   } = MyForm.formApi; \/\/ \u0432\u043d\u0443\u0442\u0440\u0438 formApi \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0444\u043e\u0440\u043c\u043e\u0439    return (     &lt;MyForm onFinish={(state) => {       \/\/ state \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d       alert(JSON.stringify(state, undefined, 2));     }}>       &lt;MyForm.Item         name=\"name\" \/\/ \u0414\u043b\u044f name \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 autocomplete         label=\"Name\"         onChange={value => {           console.log(value) \/\/ value \u0438\u043c\u0435\u0442 \u0442\u0438\u043f string         }}         rules={[           {             required: true,             message: 'Name is required',             validateTrigger: ['onFinish']           },           {            validator: async (name) => {              await validateName(name) \/\/ \u0435\u0441\u0442\u044c promise based \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438            },            message: 'Name is invalid'           }         ]}       >         {({ value, onChange }) => \/\/ value \u0438 onChange \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b, \u0442\u0443\u0442 value - string           &lt;input value={value} onChange={e => onChange(e.target.value)} \/>         }       &lt;\/MyForm.Item>       &lt;MyForm.Item name=\"age\">         {({ value, onChange }) => \/\/ \u0430 \u0442\u0443\u0442 value - number           &lt;input type=\"number\" value={value} onChange={(e) => onChange(+e.target.value)} \/>         }       &lt;\/MyForm.Item>       &lt;button type=\"submit\">         Submit button       &lt;\/button>     &lt;\/MyForm>   ) }<\/code><\/pre>\n<p>\u041d\u0435 \u0443\u0432\u0435\u0440\u0435\u043d, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u043c\u0435\u0441\u0442\u043d\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0430\u043c\u044b\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f.<\/p>\n<h2>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0444\u043e\u0440\u043c\u044b<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0441\u0442\u0435\u0439\u0442 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430\u043c \u0432\u0440\u043e\u0434\u0435 redux, \u0442\u043e \u043d\u0435 \u0442\u0430\u043a \u0443\u0436 \u043c\u043d\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e (\u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c):<\/p>\n<p>1) \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0442\u0435\u0439\u0442 \u0444\u043e\u0440\u043c\u044b \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0435\u0439\u0442\u043e\u043c \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430(\u0432 \u0432\u0438\u0434\u0435 Map\/\u043e\u0431\u044a\u0435\u043a\u0442). \u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 &#8212; \u0440\u0435\u0440\u0435\u043d\u0434\u0435\u0440 \u0432\u0441\u0435\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0444\u043e\u0440\u043c\u044b \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u0442\u0435\u0439\u0442\u0430. \u0422\u0430\u043a \u0436\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c API \u0444\u043e\u0440\u043c\u044b \u0432\u043d\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u0447\u0442\u043e \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f. \u0410 \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u044f \u043d\u0435 \u0445\u043e\u0442\u0435\u043b.<\/p>\n<p>2) \u0414\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b &#8212; \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0442\u0435\u0439\u0442 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0438 <code>Form.Item<\/code> \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>useImperativeHandle<\/code> \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0441\u0442\u0435\u0439\u0442\u043e\u043c  \u0438\u0437\u0432\u043d\u0435. \u041c\u043d\u0435 \u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0442\u0430\u043a \u0436\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 <code>Form.Item<\/code>, \u0430 \u0435\u0449\u0435 \u0436\u043e\u043d\u0433\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c ref-\u0430\u043c\u0438.<\/p>\n<p>3) \u0412\u044b\u043d\u0435\u0441\u0442\u0438 \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0444\u043e\u0440\u043c\u043e\u0439 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 <code>useRef<\/code> \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u0430 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0435\u0439\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 +  <code>useSyncExternalStore<\/code> \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044f. \u0418\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u0432 \u0438\u0442\u043e\u0433\u0435, \u043e\u043d \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043c\u043d\u0435 \u0441\u0430\u043c\u044b\u043c \u0433\u0438\u0431\u043a\u0438\u043c.<\/p>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043d\u0430 \u0441\u0442\u0435\u0439\u0442 \u043f\u043e\u043b\u044f \u0444\u043e\u0440\u043c\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"typescript\">export class FormApi&lt;State extends Record&lt;string, unknown>, Field extends GetFields&lt;State> = GetFields&lt;State>> {   private state: State   private subscribers: Map&lt;Field, FieldOnChangeCb&lt;State[Field]>[]>;    constructor(state: State) {     this.state = state;     this.subscribers = new Map();   }    getState() {     return this.state   }    onFieldChange&lt;F extends Field>(field: F, cb: FieldOnChangeCb&lt;State[F]>) {     const currentSubscribers = this.subscribers.get(field) || [];     this.subscribers.set(field, currentSubscribers.concat(cb as FieldOnChangeCb&lt;State[Field]>));      return () => { \/\/ unsubscribe       this.subscribers.set(field, this.subscribers.get(field)?.filter(i => i !== cb) || []);     }   }    private triggerFieldUpdate&lt;F extends Field, V extends State[F]>(field: F, value: V) {     this.subscribers.get(field)?.forEach(cb => cb(value));   }    setFieldsValue(update: Partial&lt;State>) {     this.state = {       ...this.state,       ...update,     }     for (const field in update) {       this.triggerFieldUpdate(field as Field, update[field] as State[Field])     }   }    setFieldValue&lt;F extends Field>(field: F, value: FieldUpdate&lt;State[F]>) {     if (typeof value === 'function') {       this.state[field] = (value as FieldsUpdateCb&lt;State[typeof field]>)(this.state[field]);     } else {       this.state[field as Field] = value     }     this.triggerFieldUpdate(field, this.state[field])   }    getFieldValue&lt;F extends Field>(field: F) {     return this.getState()[field];   } }  export const useWatch = &lt;   Form extends FormApi&lt;any>,   Types extends FormApiGenericTypes&lt;Form>,   State extends Types['state'],   Field extends Types['field'] >(form: Form, field: Field) => {   const value = useSyncExternalStore&lt;State[Field]>(     cb => form.onFieldChange(field, cb),     () => form.getFieldValue(field),     () => form.getFieldValue(field),   )    return value; }<\/code><\/pre>\n<h2>FormItem<\/h2>\n<p>\u041e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u0441\u0442\u0430\u043b API \u0434\u043b\u044f <code>FormItem<\/code>. \u041c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0442\u0430\u043a\u0443\u044e \u0436\u0435  \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0443, \u043a\u0430\u043a \u0432 <code>rc-field-form<\/code>, \u0442.\u0435. \u043d\u0435\u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"typescript\">&lt;FormItem name=\"username\">   &lt;input placeholder=\"Username\" \/> &lt;\/FormItem><\/code><\/pre>\n<p>\u043d\u043e \u0432 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>\u0412 \u0438\u0434\u0435\u0430\u043b\u0435 \u044f \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u043b \u0432 FormItem \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>normalize<\/code> \u0438 <code>getValueFromEvent<\/code> , \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c <code>value<\/code> \u043a \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443 \u0442\u0438\u043f\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0443 <code>children<\/code> \u043f\u043e\u043b\u0435\u0439 <code>value<\/code> \u0438 <code>onChange<\/code>, \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0438\u0437 \u043d\u0438\u0445 \u0442\u0438\u043f\u044b \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432  <code>normalize<\/code> \u0438 <code>getValueFromEvent<\/code> .<\/p>\n<p>\u041a \u043c\u043e\u0435\u043c\u0443 \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e JSX \u0443\u0431\u0438\u0432\u0430\u0435\u0442 \u0442\u0438\u043f\u044b \u0438 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u043f\u0441\u044b \u0438\u0437 <code>children<\/code>.  \u0421\u0430\u043c\u043e\u0435 \u0437\u0430\u0431\u0430\u0432\u043d\u043e\u0435 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 &#8212; <code>React.createElement<\/code> \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<pre><code class=\"typescript\"> type ReturnElementProps&lt;El> = El extends React.ReactElement&lt;infer P> ? P : never  type FormItemProps&lt;   Val,   El extends React.ReactElement,   Props extends ReturnElementProps&lt;El>,   ElVal = Props['value'] > = {   value: Val,   getValueFromEvent: (...args: Parameters&lt;Props['onChange']>) => Val,   normalize: (value: Val) => ElVal,   children: El }  const FormItem = &lt;Val, El extends React.ReactElement, Props extends ReturnElementProps&lt;El>>(props: FormItemProps&lt;Val, El, Props>) => {   return &lt;>{props.children}&lt;\/> }  \/\/ \u0422\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 const Test = &lt;FormItem   value={0}   getValueFromEvent={(event) => Number(event.target.value)}   normalize={(value) => String(value)} >   {React.createElement('input')} &lt;\/FormItem>  \/\/ \u0410 \u0442\u0430\u043a\u043e\u0439 - \u0443\u0436\u0435 \u043d\u0435\u0442 :( const Test2 = &lt;FormItem   value={0}    getValueFromEvent={(event) => Number(event.target.value)} \/\/ event \u0442\u0443\u0442 - unknown   normalize={(value) => String(value)} >  &lt;input \/> &lt;\/FormItem> <\/code><\/pre>\n<p>\u0425\u043e\u0442\u044f \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b &#8212; JSX \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0441\u0430\u0445\u0430\u0440\u043e\u043c \u043d\u0430\u0434 <code>createElement<\/code> \u0438 \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u0437\u0430\u0438\u043c\u043e\u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u043c\u0438. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u043d\u0435\u043a\u0438\u0439 \u0431\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u0433\u0434\u0430-\u043d\u0438\u0431\u0443\u0434\u044c \u0438\u0441\u043f\u0440\u0430\u0432\u044f\u0442. \u041d\u043e \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u044f \u043d\u0435 \u043d\u0430\u0448\u0435\u043b \u043d\u0438\u0447\u0435\u0433\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c render function \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 children:<\/p>\n<pre><code class=\"typescript\">&lt;FormItem name=\"myField\">   {({ value, onChange }) => &lt;input value={String(value)} onChange={e => onChange(Number(e.target.value))} \/>} &lt;\/FormItem><\/code><\/pre>\n<h2>\u0422\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0432\u044b\u0448\u0435, \u0441 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u0441\u0435 \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e. \u042f \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u043e\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u0431\u044b\u043b\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e, \u0430 \u044d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u0444\u0438\u0448\u0435\u043a \u0442\u0430\u0439\u043f\u0441\u043a\u0440\u0438\u043f\u0442\u0430.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u043c\u0435\u0442\u043e\u0434 <code>onFieldChange<\/code> \u0438\u043b\u0438 \u0445\u0443\u043a <code>useWatch<\/code> \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u043b\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u0435\u0439 \u0444\u043e\u0440\u043c\u044b.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0442\u0438\u043f<\/p>\n<pre><code class=\"typescript\">type Test = {   age: number   name: string }<\/code><\/pre>\n<p>\u0438 \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c <code>'age' | 'name'<\/code> &#8212; \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>keyof<\/code>, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u0435\u043d <code>Extract<\/code>, \u0447\u0442\u043e\u0431\u044b \u0442\u043e\u0447\u043d\u043e \u0431\u044b\u0442\u044c \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e \u043c\u044b \u0434\u043e\u0441\u0442\u0430\u0435\u043c <code>string<\/code>.<\/p>\n<pre><code class=\"typescript\">type GetFields&lt;T extends Record&lt;string, unknown>> = Extract&lt;keyof T, string>  type TestFields = GetFields&lt;Test> \/\/<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-375843","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/375843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=375843"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/375843\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=375843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=375843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=375843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}