{"id":476535,"date":"2026-04-19T11:15:39","date_gmt":"2026-04-19T11:15:39","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=476535"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=476535","title":{"rendered":"\u0413\u043e\u0434 \u0441 React Hook Form \u0438 Zod: \u043c\u0435\u043d\u044c\u0448\u0435 \u043a\u043e\u0434\u0430, \u043d\u043e \u043d\u0435 \u0431\u0435\u0437 \u043d\u044e\u0430\u043d\u0441\u043e\u0432"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043d\u0435 \u043e\u0448\u0438\u0431\u0443\u0441\u044c \u0435\u0441\u043b\u0438 \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0444\u043e\u0440\u043c. \u0422\u0435, \u043a\u0442\u043e \u0443\u0436\u0435 \u0438\u043c\u0435\u044e\u0442 \u0442\u0430\u043a\u043e\u0439 \u043e\u043f\u044b\u0442 \u0437\u043d\u0430\u044e\u0442, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u043e\u043b\u044c \u0438 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u044f. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u0433\u043e\u043b\u043e\u0432\u0435 \u0432\u0441\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u043e\u0440\u043c, \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438, \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0441 UI, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0438\u0437\u0431\u0435\u0433\u0430\u044f \u043b\u0438\u0448\u043d\u0438\u0445 \u0440\u0435\u0440\u0435\u043d\u0434\u0435\u0440\u043e\u0432.<\/p>\n<p>\u041d\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0444\u043e\u0440\u043c\u044b \u0447\u0435\u0440\u0435\u0437 MobX + MVC, \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u043f\u043b\u043e\u0445\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0444\u043e\u0440\u043c, \u043e\u0434\u043d\u0430\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438:<\/p>\n<h2>\u041c\u043d\u043e\u0433\u043e\u0435 \u043f\u0438\u0448\u0435\u043c \u0440\u0443\u043a\u0430\u043c\u0438<\/h2>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u043f\u0438\u0448\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0435\u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u044f. \u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a, \u0430 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u044d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0448\u0438\u0431\u043e\u043a, \u0441\u0432\u043e\u0435\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0435\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/p>\n<h2>\u041b\u0438\u0448\u043d\u0438\u0439 \u043a\u043e\u0434<\/h2>\n<p>\u041a \u043f\u0443\u043d\u043a\u0442\u0443 \u0432\u044b\u0448\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0435\u0449\u0435 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0432 Controller \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"typescript\">\/\/ SomeController.tsxexport class SomeController {  ...  public setDuration = (v: number) =&gt; {    this.store.duration = v;  }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e &#171;\u043c\u0443\u0441\u043e\u0440\u043d\u043e\u0433\u043e&#187; \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u043e\u0439. \u041d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0434\u043d\u043e \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 ? \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u0434 \u043d\u0435\u0433\u043e \u043a\u0443\u0447\u0443 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c &#171;\u043c\u0435\u0442\u0430&#187; \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e.<\/p>\n<p>\u0412\u043e\u0442 \u0437\u0434\u0435\u0441\u044c \u0432 \u0438\u0433\u0440\u0443 \u0432\u0441\u0442\u0443\u043f\u0430\u0435\u0442 React Hook Form + Zod. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u044b \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u044b (RHF + Zod):<\/strong><\/p>\n<pre><code class=\"typescript\">import { useForm } from 'react-hook-form';import { zodResolver } from '@hookform\/resolvers\/zod';import { z } from 'zod';const formSchema = z.object({  name: z.string().min(1, '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f'),  email: z.string().email('\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 email'),  age: z.coerce.number().min(0, '\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0432\u043e\u0437\u0440\u0430\u0441\u0442').optional(),});type FormValues = z.infer&lt;typeof formSchema&gt;;export function ExampleForm() {  const {    register,    handleSubmit,    formState: { errors },  } = useForm&lt;FormValues&gt;({    resolver: zodResolver(formSchema),    defaultValues: {      name: '',      email: '',    },  });  return (    &lt;form onSubmit={handleSubmit((data) =&gt; console.log(data))}&gt;      &lt;div&gt;        &lt;input {...register('name')} \/&gt;        {errors.name &amp;&amp; &lt;span&gt;{errors.name.message}&lt;\/span&gt;}      &lt;\/div&gt;      &lt;div&gt;        &lt;input type=\"email\" {...register('email')} \/&gt;        {errors.email &amp;&amp; &lt;span&gt;{errors.email.message}&lt;\/span&gt;}      &lt;\/div&gt;      &lt;div&gt;        &lt;input type=\"number\" {...register('age')} \/&gt;        {errors.age &amp;&amp; &lt;span&gt;{errors.age.message}&lt;\/span&gt;}      &lt;\/div&gt;      &lt;button type=\"submit\"&gt;\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c&lt;\/button&gt;    &lt;\/form&gt;  );}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u0440\u0430\u0437\u0434\u0435\u043b \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u044d\u0442\u0438\u0445 \u0438\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0442\u043e \u0431\u044b\u043b\u0438 \u043f\u0440\u0438\u044f\u0442\u043d\u043e \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u044b \u043c\u0435\u043d\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043a\u043e\u0434\u0430 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u043e\u0439.<\/p>\n<h2>\u041d\u0435 \u0432\u0441\u0435 \u0442\u0430\u043a \u0433\u043b\u0430\u0434\u043a\u043e<\/h2>\n<p>\u0421 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f React Hook Form \u0432 \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u043e\u0448\u0435\u043b \u0443\u0436\u0435 \u0433\u043e\u0434, \u043c\u043e\u0433\u0443 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0444\u043e\u0440\u043c\u044b \u0432 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0438 \u043d\u043e\u0432\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e. \u041e\u0434\u043d\u0430\u043a\u043e \u0437\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u0441\u044f \u0440\u044f\u0434 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432.<\/p>\n<p><strong>1. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 <\/strong><code><strong>undefined<\/strong><\/code><strong> \u043f\u043e\u043b\u044f\u043c\u0438.<\/strong><\/p>\n<p>\u041e\u043f\u0438\u0441\u044b\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u0432\u043e\u0435\u0439 \u0444\u043e\u0440\u043c\u044b, \u0432\u044b \u0437\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0435 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f.<\/p>\n<pre><code class=\"typescript\">const schema = z.object({  age: z.number()});\/\/ \u041c\u0435\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044fmethods.setValue('age', undefined)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412\u043f\u043e\u043b\u043d\u0435 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434, \u0434\u0430 \u0432\u043e\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u0438\u0435\u043c \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u044d\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e:<\/p>\n<blockquote>\n<p>The value for the field. This argument is required and can not be\u00a0<code>undefined<\/code>.<\/p>\n<\/blockquote>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e. \u041f\u043e\u0438\u0441\u043a\u0430\u0432 issues \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u0432\u044b \u043d\u0430\u0439\u0434\u0435\u0442\u0435 \u043c\u043d\u043e\u0433\u043e \u0442\u0430\u043a\u0438\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <a href=\"https:\/\/github.com\/react-hook-form\/react-hook-form\/issues\/12277\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442<\/a>\u00a0\u0438\u043b\u0438 <a href=\"https:\/\/github.com\/orgs\/react-hook-form\/discussions\/5858\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442<\/a>. \u041c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043b\u044e\u0434\u0435\u0439 \u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0443\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code class=\"typescript\">const schema = z.object({  age: z.number().nullable()});\/\/ \u041c\u0435\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044fmethods.setValue('age', null)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u0430\u043a \u043f\u043e \u043c\u043d\u0435, \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u043e\u0441\u0442\u044b\u043b\u044c\u043d\u043e \u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432 \u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043b\u043e\u043c\u0430\u0435\u0442 \u043a\u0438\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u0432\u043e\u0434\u0430 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u0432 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c <code>null<\/code>. \u0418\u043d\u043e\u0433\u0434\u0430 \u0431\u044b\u0432\u0430\u0435\u0442 \u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442 &#8212; \u043a\u0438\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0442\u0434\u0430\u0435\u0442 <code>undefined<\/code> \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043e\u0447\u0438\u0441\u0442\u043a\u0435 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u043c\u043d\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u043f\u043e\u043b\u043d\u043e\u0439 \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0444\u043e\u0440\u043c\u044b \u043a \u043f\u0443\u0441\u0442\u044b\u043c \u043f\u043e\u043b\u044f\u043c. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044d\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c &#8212; \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u0438 \u043d\u0430 <code>onClick<\/code> \u0432\u0435\u0448\u0430\u0435\u043c <code>methods.reset()<\/code>, \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0443 \u043a <code>default<\/code> \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0444\u043e\u0440\u043c\u044b: <\/p>\n<pre><code class=\"typescript\"> const methods = useForm&lt;FormValues&gt;({    resolver: zodResolver(formSchema),    defaultValues: {      name: undefined,      email: undefined,    },  });<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u043e \u0442\u0443\u0442 \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u043f\u043e\u043b\u0435 \u0432 <code>undefined<\/code> \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.  \u0421\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044f <code>.nullable()<\/code> \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0430\u043a:<\/p>\n<pre><code class=\"typescript\"> const methods = useForm&lt;FormValues&gt;({    resolver: zodResolver(formSchema),    defaultValues: {      name: null,      email: null,    },  });<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u0448\u0435 \u043f\u043e\u043b\u0435 \u0441\u0442\u0440\u043e\u043a\u0430, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043d\u0435 <code>null<\/code> \u0430 <code>''<\/code>, \u044d\u0442\u043e \u0442\u043e\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<p><strong>2. \u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442 Zod<\/strong><\/p>\n<p>\u042d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u043d\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 React Hook Form \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e. \u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 Zod. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u0445\u0435\u043c\u0443 \u0432\u0438\u0434\u0430:<\/p>\n<pre><code class=\"typescript\">const schema = z.object({  field1: z.string().min(1, '\u0417\u0430\u043f\u043e\u043b\u043d\u0438 \u043f\u043e\u043b\u0435').optional()});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438 \u043e\u0447\u0438\u0441\u0442\u043a\u0435 \u043e\u0442\u0434\u0430\u0435\u0442 <code>null<\/code>, \u0433\u043e\u0442\u043e\u0432\u044c\u0442\u0435\u0441\u044c \u043b\u043e\u0432\u0438\u0442\u044c \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443 <code>invalid type (expected string received null)<\/code>. <\/p>\n<p>\u0412\u0430\u0448\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u044d\u0442\u043e \u044f\u0432\u043d\u043e \u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u0427\u0442\u043e\u0431\u044b \u0442\u0430\u043a\u0438\u0445 \u0441\u0442\u0443\u0430\u0446\u0438\u0439 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a:<\/p>\n<pre><code class=\"typescript\">\/\/ zod v4const schema = z.object({  field1: z.string('\u0417\u0430\u043f\u043e\u043b\u043d\u0438 \u043f\u043e\u043b\u0435').min(1, '\u0417\u0430\u043f\u043e\u043b\u043d\u0438 \u043f\u043e\u043b\u0435').optional()});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>3. \u041c\u0430\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 isDirty<\/strong><\/p>\n<p>\u0424\u043b\u0430\u0433, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u044b\u0439 \u0438\u0437 <code>methods.formState.isDirty,<\/code> \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0435\u0441\u0442\u044c \u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043d\u0430 \u0432\u0430\u0448\u0435\u0439 \u0444\u043e\u0440\u043c\u0435. \u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043b \u0444\u043e\u0440\u043c\u0443 \u0438 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0439\u0442\u0438 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0444\u043b\u0430\u0433\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u0431\u0443\u0434\u044c\u0442\u0435 \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u044b \u0441 \u0442\u0430\u043a\u0438\u043c \u043a\u0435\u0439\u0441\u043e\u043c:<\/p>\n<pre><code class=\"typescript\">const formSchema = z.object({  name: z.string().min(1, '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f'),  age: z.coerce.number().min(0, '\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0432\u043e\u0437\u0440\u0430\u0441\u0442').optional(),});export function ExampleForm() {  const methods = useForm({    resolver: zodResolver(formSchema),    defaultValues: {},  });  \/\/ \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 true, \u0445\u043e\u0442\u044f \u0435\u0449\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u0438!  const isDirty = methods.formState.isDirty;  \/\/ \u0417\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 {}  const dirtyFields = methods.formState.dirtyFields;  return ...;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u043c, \u0432\u0441\u0435 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u0432 defaultValues \u043f\u0443\u0441\u0442\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442.<\/p>\n<h3>\u0412\u044b\u0432\u043e\u0434<\/h3>\n<p>\u0421\u043b\u043e\u0436\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043e\u0442\u043d\u0438\u043c\u0430\u044e\u0442 \u043c\u043d\u043e\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f, \u043d\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0441\u043d\u044f\u0442\u044c \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043b\u0438\u0448\u043d\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0441 \u0440\u0443\u0447\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0441\u0442\u0438\u043b\u0435 MobX \u0438 MVC \u043d\u0430 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 React Hook Form \u0438 Zod \u0443 \u043d\u0430\u0441 \u043e\u043a\u0443\u043f\u0438\u043b\u0441\u044f: \u0444\u043e\u0440\u043c\u044b \u043f\u0440\u043e\u0449\u0435 \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u043c\u0435\u043d\u044f\u0442\u044c. <\/p>\n<p>\u0417\u0430 \u0433\u043e\u0434 \u0432 \u043f\u0440\u043e\u0434\u0435 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u043b\u0438 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e\u0441\u0442\u0438, \u0431\u0435\u0437 \u043d\u0438\u0445 \u043d\u0435 \u043e\u0431\u043e\u0448\u043b\u043e\u0441\u044c. \u0412 \u0446\u0435\u043b\u043e\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u044b \u043d\u0435 \u0436\u0430\u043b\u0435\u0435\u043c \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u043d\u0430 \u043d\u0451\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b. \u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u0438\u0442\u043e\u0433 \u043f\u0440\u043e\u0441\u0442\u043e\u0439: \u0432\u044b\u0431\u0438\u0440\u0430\u0439\u0442\u0435 \u0441\u0442\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0440\u0443\u0442\u0438\u043d\u0443, \u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043a \u0434\u0435\u0442\u0430\u043b\u044f\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u0442\u043e\u0433\u0434\u0430 \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435.<\/p>\n<\/div>\n<p>\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\/1025218\/\">https:\/\/habr.com\/ru\/articles\/1025218\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043d\u0435 \u043e\u0448\u0438\u0431\u0443\u0441\u044c \u0435\u0441\u043b\u0438 \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0444\u043e\u0440\u043c. \u0422\u0435, \u043a\u0442\u043e \u0443\u0436\u0435 \u0438\u043c\u0435\u044e\u0442 \u0442\u0430\u043a\u043e\u0439 \u043e\u043f\u044b\u0442 \u0437\u043d\u0430\u044e\u0442, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u043e\u043b\u044c \u0438 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u044f. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u0433\u043e\u043b\u043e\u0432\u0435 \u0432\u0441\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u043e\u0440\u043c, \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438, \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0441 UI, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0438\u0437\u0431\u0435\u0433\u0430\u044f \u043b\u0438\u0448\u043d\u0438\u0445 \u0440\u0435\u0440\u0435\u043d\u0434\u0435\u0440\u043e\u0432.\u041d\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0444\u043e\u0440\u043c\u044b \u0447\u0435\u0440\u0435\u0437 MobX + MVC, \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u043f\u043b\u043e\u0445\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0444\u043e\u0440\u043c, \u043e\u0434\u043d\u0430\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438:\u041c\u043d\u043e\u0433\u043e\u0435 \u043f\u0438\u0448\u0435\u043c \u0440\u0443\u043a\u0430\u043c\u0438\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u043f\u0438\u0448\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0435\u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u044f. \u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a, \u0430 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u044d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0448\u0438\u0431\u043e\u043a, \u0441\u0432\u043e\u0435\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0435\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u041b\u0438\u0448\u043d\u0438\u0439 \u043a\u043e\u0434\u041a \u043f\u0443\u043d\u043a\u0442\u0443 \u0432\u044b\u0448\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0435\u0449\u0435 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0432 Controller \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:\/\/ SomeController.tsxexport class SomeController {  &#8230;  public setDuration = (v: number) =&gt; {    this.store.duration = v;  }}\u041f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e &#171;\u043c\u0443\u0441\u043e\u0440\u043d\u043e\u0433\u043e&#187; \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u043e\u0439. \u041d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0434\u043d\u043e \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 ? \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u0434 \u043d\u0435\u0433\u043e \u043a\u0443\u0447\u0443 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c &#171;\u043c\u0435\u0442\u0430&#187; \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e.\u0412\u043e\u0442 \u0437\u0434\u0435\u0441\u044c \u0432 \u0438\u0433\u0440\u0443 \u0432\u0441\u0442\u0443\u043f\u0430\u0435\u0442 React Hook Form + Zod. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u044b \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e.\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u044b (RHF + Zod):import { useForm } from &#8216;react-hook-form&#8217;;import { zodResolver } from &#8216;@hookform\/resolvers\/zod&#8217;;import { z } from &#8216;zod&#8217;;const formSchema = z.object({  name: z.string().min(1, &#8216;\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f&#8217;),  email: z.string().email(&#8216;\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 email&#8217;),  age: z.coerce.number().min(0, &#8216;\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0432\u043e\u0437\u0440\u0430\u0441\u0442&#8217;).optional(),});type FormValues = z.infer&lt;typeof formSchema&gt;;export function ExampleForm() {  const {    register,    handleSubmit,    formState: { errors },  } = useForm&lt;FormValues&gt;({    resolver: zodResolver(formSchema),    defaultValues: {      name: &#187;,      email: &#187;,    },  });  return (    &lt;form onSubmit={handleSubmit((data) =&gt; console.log(data))}&gt;      &lt;div&gt;        &lt;input {&#8230;register(&#8216;name&#8217;)} \/&gt;        {errors.name &amp;&amp; &lt;span&gt;{errors.name.message}&lt;\/span&gt;}      &lt;\/div&gt;      &lt;div&gt;        &lt;input type=&#187;email&#187; {&#8230;register(&#8217;email&#8217;)} \/&gt;        {errors.email &amp;&amp; &lt;span&gt;{errors.email.message}&lt;\/span&gt;}      &lt;\/div&gt;      &lt;div&gt;        &lt;input type=&#187;number&#187; {&#8230;register(&#8216;age&#8217;)} \/&gt;        {errors.age &amp;&amp; &lt;span&gt;{errors.age.message}&lt;\/span&gt;}      &lt;\/div&gt;      &lt;button type=&#187;submit&#187;&gt;\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c&lt;\/button&gt;    &lt;\/form&gt;  );}\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u0440\u0430\u0437\u0434\u0435\u043b \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u044d\u0442\u0438\u0445 \u0438\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0442\u043e \u0431\u044b\u043b\u0438 \u043f\u0440\u0438\u044f\u0442\u043d\u043e \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u044b \u043c\u0435\u043d\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043a\u043e\u0434\u0430 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u043e\u0439.\u041d\u0435 \u0432\u0441\u0435 \u0442\u0430\u043a \u0433\u043b\u0430\u0434\u043a\u043e\u0421 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f React Hook Form \u0432 \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u043e\u0448\u0435\u043b \u0443\u0436\u0435 \u0433\u043e\u0434, \u043c\u043e\u0433\u0443 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0444\u043e\u0440\u043c\u044b \u0432 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0438 \u043d\u043e\u0432\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e. \u041e\u0434\u043d\u0430\u043a\u043e \u0437\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u0441\u044f \u0440\u044f\u0434 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432.1. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 undefined \u043f\u043e\u043b\u044f\u043c\u0438.\u041e\u043f\u0438\u0441\u044b\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u0432\u043e\u0435\u0439 \u0444\u043e\u0440\u043c\u044b, \u0432\u044b \u0437\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0435 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f.const schema = z.object({  age: z.number()});\/\/ \u041c\u0435\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044fmethods.setValue(&#8216;age&#8217;, undefined)\u0412\u043f\u043e\u043b\u043d\u0435 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434, \u0434\u0430 \u0432\u043e\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u0438\u0435\u043c \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u044d\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e:The value for the field. This argument is required and can not be\u00a0undefined.\u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e. \u041f\u043e\u0438\u0441\u043a\u0430\u0432 issues \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u0432\u044b \u043d\u0430\u0439\u0434\u0435\u0442\u0435 \u043c\u043d\u043e\u0433\u043e \u0442\u0430\u043a\u0438\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u043e\u0442\u00a0\u0438\u043b\u0438 \u0432\u043e\u0442. \u041c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043b\u044e\u0434\u0435\u0439 \u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0443\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:const schema = z.object({  age: z.number().nullable()});\/\/ \u041c\u0435\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044fmethods.setValue(&#8216;age&#8217;, null)\u041a\u0430\u043a \u043f\u043e \u043c\u043d\u0435, \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u043e\u0441\u0442\u044b\u043b\u044c\u043d\u043e \u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432 \u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043b\u043e\u043c\u0430\u0435\u0442 \u043a\u0438\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u0432\u043e\u0434\u0430 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u0432 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c null. \u0418\u043d\u043e\u0433\u0434\u0430 \u0431\u044b\u0432\u0430\u0435\u0442 \u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442 &#8212; \u043a\u0438\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0442\u0434\u0430\u0435\u0442 undefined \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043e\u0447\u0438\u0441\u0442\u043a\u0435 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u043c\u043d\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u043f\u043e\u043b\u043d\u043e\u0439 \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0444\u043e\u0440\u043c\u044b \u043a \u043f\u0443\u0441\u0442\u044b\u043c \u043f\u043e\u043b\u044f\u043c. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044d\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c &#8212; \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u0438 \u043d\u0430 onClick \u0432\u0435\u0448\u0430\u0435\u043c methods.reset(), \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0443 \u043a default \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0444\u043e\u0440\u043c\u044b:  const methods = useForm&lt;FormValues&gt;({    resolver: zodResolver(formSchema),    defaultValues: {      name: undefined,      email: undefined,    },  });\u041d\u043e \u0442\u0443\u0442 \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u043f\u043e\u043b\u0435 \u0432 undefined \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.  \u0421\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044f .nullable() \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0430\u043a: const methods = useForm&lt;FormValues&gt;({    resolver: zodResolver(formSchema),    defaultValues: {      name: null,      email: null,    },  });\u0415\u0441\u043b\u0438 \u0432\u0430\u0448\u0435 \u043f\u043e\u043b\u0435 \u0441\u0442\u0440\u043e\u043a\u0430, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043d\u0435 null \u0430 &#187;, \u044d\u0442\u043e \u0442\u043e\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.2. \u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442 Zod\u042d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u043d\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 React Hook Form \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e. \u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 Zod. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u0445\u0435\u043c\u0443 \u0432\u0438\u0434\u0430:const schema = z.object({  field1: z.string().min(1, &#8216;\u0417\u0430\u043f\u043e\u043b\u043d\u0438 \u043f\u043e\u043b\u0435&#8217;).optional()});\u0414\u0430\u043b\u0435\u0435 \u0432\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438 \u043e\u0447\u0438\u0441\u0442\u043a\u0435 \u043e\u0442\u0434\u0430\u0435\u0442 null, \u0433\u043e\u0442\u043e\u0432\u044c\u0442\u0435\u0441\u044c \u043b\u043e\u0432\u0438\u0442\u044c \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443 invalid type (expected string received null). \u0412\u0430\u0448\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u044d\u0442\u043e \u044f\u0432\u043d\u043e \u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u0427\u0442\u043e\u0431\u044b \u0442\u0430\u043a\u0438\u0445 \u0441\u0442\u0443\u0430\u0446\u0438\u0439 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a:\/\/ zod v4const schema = z.object({  field1: z.string(&#8216;\u0417\u0430\u043f\u043e\u043b\u043d\u0438 \u043f\u043e\u043b\u0435&#8217;).min(1, &#8216;\u0417\u0430\u043f\u043e\u043b\u043d\u0438 \u043f\u043e\u043b\u0435&#8217;).optional()});3. \u041c\u0430\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 isDirty\u0424\u043b\u0430\u0433, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u044b\u0439 \u0438\u0437 methods.formState.isDirty, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0435\u0441\u0442\u044c \u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043d\u0430 \u0432\u0430\u0448\u0435\u0439 \u0444\u043e\u0440\u043c\u0435. \u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043b \u0444\u043e\u0440\u043c\u0443 \u0438 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0439\u0442\u0438 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0444\u043b\u0430\u0433\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u0431\u0443\u0434\u044c\u0442\u0435 \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u044b \u0441 \u0442\u0430\u043a\u0438\u043c \u043a\u0435\u0439\u0441\u043e\u043c:const formSchema = z.object({  name: z.string().min(1, &#8216;\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f&#8217;),  age: z.coerce.number().min(0, &#8216;\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0432\u043e\u0437\u0440\u0430\u0441\u0442&#8217;).optional(),});export function ExampleForm() {  const methods = useForm({    resolver: zodResolver(formSchema),    defaultValues: {},  });  \/\/ \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 true, \u0445\u043e\u0442\u044f \u0435\u0449\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u0438!  const isDirty = methods.formState.isDirty;  \/\/ \u0417\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 {}  const dirtyFields = methods.formState.dirtyFields;  return &#8230;;}\u042d\u0442\u043e \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u043c, \u0432\u0441\u0435 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u0432 defaultValues \u043f\u0443\u0441\u0442\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442.\u0412\u044b\u0432\u043e\u0434\u0421\u043b\u043e\u0436\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043e\u0442\u043d\u0438\u043c\u0430\u044e\u0442 \u043c\u043d\u043e\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f, \u043d\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0441\u043d\u044f\u0442\u044c \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043b\u0438\u0448\u043d\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0441 \u0440\u0443\u0447\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0441\u0442\u0438\u043b\u0435 MobX \u0438 MVC \u043d\u0430 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 React Hook Form \u0438 Zod \u0443 \u043d\u0430\u0441 \u043e\u043a\u0443\u043f\u0438\u043b\u0441\u044f: \u0444\u043e\u0440\u043c\u044b \u043f\u0440\u043e\u0449\u0435 \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u043c\u0435\u043d\u044f\u0442\u044c. \u0417\u0430 \u0433\u043e\u0434 \u0432 \u043f\u0440\u043e\u0434\u0435 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u043b\u0438 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e\u0441\u0442\u0438, \u0431\u0435\u0437 \u043d\u0438\u0445 \u043d\u0435 \u043e\u0431\u043e\u0448\u043b\u043e\u0441\u044c. \u0412 \u0446\u0435\u043b\u043e\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u044b \u043d\u0435 \u0436\u0430\u043b\u0435\u0435\u043c \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u043d\u0430 \u043d\u0451\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b. \u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u0438\u0442\u043e\u0433 \u043f\u0440\u043e\u0441\u0442\u043e\u0439: \u0432\u044b\u0431\u0438\u0440\u0430\u0439\u0442\u0435 \u0441\u0442\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0440\u0443\u0442\u0438\u043d\u0443, \u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043a \u0434\u0435\u0442\u0430\u043b\u044f\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u0442\u043e\u0433\u0434\u0430 \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435.\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 https:\/\/habr.com\/ru\/articles\/1025218\/<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-476535","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/476535","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=476535"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/476535\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=476535"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=476535"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=476535"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}