{"id":1238,"date":"2021-09-16T10:45:42","date_gmt":"2021-09-16T01:45:42","guid":{"rendered":"https:\/\/weseek.co.jp\/tech\/?p=1238"},"modified":"2023-04-17T10:28:26","modified_gmt":"2023-04-17T01:28:26","slug":"react-%e3%81%a7%e3%83%95%e3%82%a9%e3%83%bc%e3%83%a0%e3%82%92%e3%82%b9%e3%83%9e%e3%83%bc%e3%83%88%e3%81%ab%e5%ae%9f%e8%a3%85%e3%81%99%e3%82%8b","status":"publish","type":"post","link":"https:\/\/weseek.co.jp\/tech\/1238\/","title":{"rendered":"React\u3067\u30d5\u30a9\u30fc\u30e0\u3092\u30b9\u30de\u30fc\u30c8\u306b\u5b9f\u88c5"},"content":{"rendered":"<p>\u3053\u306e\u8a18\u4e8b\u306f\u30012021\/9\/2 \u306b\u884c\u308f\u308c\u305f WESEEK Tech Conference \u306e\u5185\u5bb9\u3092\u307e\u3068\u3081\u305f\u3082\u306e\u3067\u3059\u3002<\/p>\n<p><!--more--><\/p>\n<h1>\u76ee\u6b21<\/h1>\n\n<h1>\u306f\u3058\u3081\u306b<\/h1>\n<p>\u3053\u306e\u8a18\u4e8b\u3067\u306f\u30d5\u30a9\u30fc\u30e0\u306e\u57fa\u790e\u306b\u3064\u3044\u3066\u6271\u3044, \u305d\u306e\u5f8c React \u3067\u306e\u30d5\u30a9\u30fc\u30e0\u306e\u57fa\u790e, \u5b9f\u88c5\u3092\u3057\u3066\u307f\u3066\u30e9\u30a4\u30d6\u30e9\u30ea (react-hook-form) \u3092\u5c0e\u5165\u3059\u308b\u8a71, react-hook-form \u306e\u57fa\u790e\u3068\u5c0e\u5165\u4f8b\u306b\u3064\u3044\u3066\u6271\u3044\u307e\u3059<\/p>\n<h2>\u5bfe\u8c61\u8aad\u8005\u3068\u3053\u306e\u8a18\u4e8b\u3067\u6271\u3046\u5185\u5bb9<\/h2>\n<ul>\n<li>React \u306e\u30d5\u30a9\u30fc\u30e0\u306e\u57fa\u790e\u3092\u77e5\u308a\u305f\u3044\n<ul>\n<li>\u30d5\u30a9\u30fc\u30e0\u3063\u3066\u306a\u3093\u3060\u308d\u3046<\/li>\n<li>Controlled or Uncontrolled \u3068\u305d\u306e\u57fa\u790e<\/li>\n<\/ul>\n<\/li>\n<li>react-hook-form \u306b\u3064\u3044\u3066\u77e5\u308a\u305f\u3044\n<ul>\n<li>\u57fa\u790e<br \/>\nTips, GROWI.cloud \u3067\u306e\u5c0e\u5165\u4e8b\u4f8b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><!--more--><\/p>\n<h2>\u305d\u3082\u305d\u3082\u30d5\u30a9\u30fc\u30e0\u3069\u3046\u3044\u3046\u3082\u306e ?<\/h2>\n<p>\u30e6\u30fc\u30b6\u3068\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u5bfe\u8a71\u3092\u8868\u73fe\u3057\u3066\u3044\u308b\u3082\u306e\u3002\u3044\u308d\u3044\u308d\u7a2e\u985e\u304c\u3042\u308b\u3002<\/p>\n<h3>\u4e00\u756a\u5358\u7d14\u306a\u30d5\u30a9\u30fc\u30e0\u304b\u3089\u8003\u3048\u3066\u307f\u308b<\/h3>\n<ul>\n<li>\n<img loading=\"lazy\" src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/simple-form.jpg\" alt=\"\" width=\"457\" height=\"72\" class=\"aligncenter size-full wp-image-1239\" srcset=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/simple-form.jpg 457w, https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/simple-form-300x47.jpg 300w, https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/simple-form-304x48.jpg 304w, https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/simple-form-282x44.jpg 282w\" sizes=\"(max-width: 457px) 100vw, 457px\" \/>\n<\/li>\n<\/ul>\n<p>\u540d\u524d\u3092\u5165\u529b\u3057\u305f\u3089 Submit \u3092\u62bc\u3059, \u305d\u306e\u30bf\u30a4\u30df\u30f3\u30b0\u3067\u5165\u529b\u3057\u305f\u3089\u4f55\u304b\u304c\u8d77\u3053\u308b\u3088\u3046\u306a\u30b7\u30f3\u30d7\u30eb\u306a\u30d5\u30a9\u30fc\u30e0<\/p>\n<ul>\n<li>\n<p>\u30b3\u30fc\u30c9\u306b\u8d77\u3053\u3059\u3068\u3053\u3046\u3044\u3046\u611f\u3058<\/p>\n<pre><code>&lt;form action=\u201d\/name\u201d method=\u201dpost\u201d&gt;\n&lt;label&gt;\n    Name:\n    &lt;input type=&quot;text&quot; name=&quot;name&quot; \/&gt;\n&lt;\/label&gt;\n&lt;input type=&quot;submit&quot; value=&quot;Submit&quot; \/&gt;\n&lt;\/form&gt;<\/code><\/pre>\n<ul>\n<li>form \u30bf\u30b0\u3067\u56f2\u3046\n<ul>\n<li>Submit \u6642\u306e\u6319\u52d5\u3092\u66f8\u3044\u3066\u304a\u304f<\/li>\n<\/ul>\n<\/li>\n<li>input \u30bf\u30b0\u3067, \u5165\u529b\u6b04\u3068 Submit \u30dc\u30bf\u30f3\u3092\u8868\u73fe<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>\u3053\u306e\u30d5\u30a9\u30fc\u30e0\u304b\u3089\u308f\u304b\u308b\u3053\u3068<\/h4>\n<ul>\n<li>DOM \u5185\u90e8\u306b\u72b6\u614b\u3092\u6301\u3063\u3066\u3044\u308b\u3053\u3068\n<ul>\n<li>\u4eca\u56de\u3067\u3044\u3046\u3068\u30e6\u30fc\u30b6\u304c\u5165\u529b\u3057\u305f Name<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>\u30d5\u30a9\u30fc\u30e0\u306b\u3082\u7a2e\u985e\u304c\u3042\u308b<\/h3>\n<p><img src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/simple-form-others.jpg\" alt=\"\" \/><\/p>\n<ul>\n<li>\u5de6\u306b\u3042\u308b\u306e\u306f\u30bb\u30ec\u30af\u30c8\u30dc\u30c3\u30af\u30b9\n<ul>\n<li>\u30c9\u30ed\u30c3\u30d7\u30c0\u30a6\u30f3\u5f62\u5f0f\u306b\u306a\u3063\u3066\u3044\u3066, \u8907\u6570\u306e\u3046\u3061\u304b\u3089\u4e00\u3064\u9078\u3076\u3088\u3046\u306a\u3082\u306e<\/li>\n<\/ul>\n<\/li>\n<li>\u53f3\u306b\u3042\u308b\u30d5\u30a9\u30fc\u30e0\u306f\u540d\u524d, \u51fa\u8eab\u5730, \u30e1\u30e2\u30683\u3064\u306e\u8981\u7d20\u3092\u307e\u3068\u3081\u3066 Submit \u3059\u308b\u3088\u3046\u306a\u3082\u306e<\/li>\n<\/ul>\n<p>\u30d5\u30a9\u30fc\u30e0\u306f\u30e6\u30fc\u30b6\u3068\u306e\u5bfe\u8a71\u3092\u8868\u73fe\u3059\u308b\u3053\u3068\u304c\u308f\u304b\u308b<\/p>\n<h3>\u5c11\u3057\u8907\u96d1\u306a\u30d5\u30a9\u30fc\u30e0<\/h3>\n<p><img src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/form-sample.jpg\" alt=\"\" \/><\/p>\n<ul>\n<li>\u3053\u308c\u306f GROWI.cloud \u3067\u4f7f\u3063\u3066\u3044\u308b\u30d5\u30a9\u30fc\u30e0<\/li>\n<li>\u5c11\u3057\u8907\u96d1, \u69cb\u6210\u8981\u7d20\u304c\u591a\u3044\n<ul>\n<li>\u4e0a\u4e0b\u3067\u4e00\u3064\u306e\u30d5\u30a9\u30fc\u30e0\u3067\u3042\u308a, \u300c\u72ec\u81ea\u30c9\u30e1\u30a4\u30f3\u3092\u5229\u7528\u3059\u308b\u300d\u3092\u62bc\u3059\u3068\u5207\u308a\u66ff\u308f\u308b<\/li>\n<li>\u4e0a\u306e\u30d5\u30a9\u30fc\u30e0\n<ul>\n<li>\u5165\u529b\u4e2d\u306e\u5185\u5bb9\u3092\u3059\u3050\u4e0b\u306b\u8868\u793a\u3059\u308b<\/li>\n<li>\u5165\u529b\u3057\u305f\u5185\u5bb9\u304c url \u3068\u3057\u3066\u6b63\u3057\u304f\u306a\u3044\u5834\u5408\u30a8\u30e9\u30fc\u3092\u51fa\u3059 (validation \u3068 error \u8868\u793a)<\/li>\n<\/ul>\n<\/li>\n<li>\u4e0b\u306e\u30d5\u30a9\u30fc\u30e0\n<ul>\n<li>\u5165\u529b\u3057\u305f\u5185\u5bb9\u304c url \u3068\u3057\u3066\u6b63\u3057\u304f\u306a\u3044\u5834\u5408\u30a8\u30e9\u30fc\u3092\u51fa\u3059 (validation \u3068 error \u8868\u793a)<\/li>\n<li>SSL\u8a3c\u660e\u66f8 (\u30d5\u30a1\u30a4\u30eb) \u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u3068\u3044\u3046\u3088\u3046\u306b\u30d5\u30a9\u30fc\u30e0\u306e\u8981\u7d20\u304c\u5897\u3048\u308b\u3053\u3068\u3082\u3042\u308b<br \/>\n\u305d\u306e\u969b, \u30d5\u30a9\u30fc\u30e0\u5185\u90e8\u306b\u6301\u3064\u72b6\u614b\u304c\u591a\u3044\u306e\u3067\u8a2d\u8a08\u304c\u5927\u5909\u306b\u306a\u308a\u3084\u3059\u3044<br \/>\n\u307e\u305f\u308f\u305a\u3089\u308f\u3057\u3044(e.g. \u5de8\u5927, \u91cd\u3044)\u30d5\u30a9\u30fc\u30e0\u3092\u4f5c\u308b\u3068\u30e6\u30fc\u30b6\u96e2\u308c\u3066\u3057\u307e\u3046\u304b\u3082\u3057\u308c\u306a\u3044<\/p>\n<p>-&gt; \u30d5\u30a9\u30fc\u30e0\u306e\u8a2d\u8a08\u306f\u5927\u4e8b\u306b\u306a\u308b<\/p>\n<h3>\u307e\u3068\u3081\u308b\u3068<\/h3>\n<ul>\n<li>\u30d5\u30a9\u30fc\u30e0\u306f\u30e6\u30fc\u30b6\u3068\u306e\u5bfe\u8a71<\/li>\n<li>\u30d5\u30a9\u30fc\u30e0\u3092\u69cb\u6210\u3059\u308b\u8981\u7d20\u304c\u591a\u3044\u306e\u3067\u8a2d\u8a08\u304c\u5927\u4e8b<\/li>\n<\/ul>\n<h2>React \u30d5\u30a9\u30fc\u30e0\u306e\u57fa\u790e<\/h2>\n<h3>React \u306e\u30d5\u30a9\u30fc\u30e0\u5b9f\u88c5\u306f2\u7a2e\u985e\u3042\u308b<\/h3>\n<ul>\n<li>Uncontrolled Component\n<ul>\n<li>\u30d5\u30a9\u30fc\u30e0\u306e\u72b6\u614b\u3092 react \u306e state \u3067\u7ba1\u7406\u3057\u306a\u3044\n<ul>\n<li>DOM \u304c\u7ba1\u7406\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<li>\u6bd4\u8f03\u7684\u9ad8\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9<\/li>\n<li>\u30b7\u30f3\u30d7\u30eb\u306a\u30d5\u30a9\u30fc\u30e0\u3092\u30b7\u30f3\u30d7\u30eb\u306b\u5b9f\u88c5\u3067\u304d\u308b<\/li>\n<\/ul>\n<\/li>\n<li>Controlled Component\n<ul>\n<li>\u30d5\u30a9\u30fc\u30e0\u306e\u72b6\u614b\u3092 react \u306e state \u3067\u7ba1\u7406\u3059\u308b<\/li>\n<li>\u51dd\u3063\u305f\u30d5\u30a9\u30fc\u30e0\u3092\u4f5c\u308a\u3084\u3059\u3044<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>Uncontrolled Component<\/h3>\n<p>\u7c21\u5358\u306a\u30d5\u30a9\u30fc\u30e0\u3092 Uncontrolled Component \u3067\u66f8\u3044\u3066\u307f\u308b<\/p>\n<p><img src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/react-form-sample.jpg\" alt=\"\" \/><\/p>\n<p>\u30b3\u30fc\u30c9\u306b\u8d77\u3053\u3059<\/p>\n<pre><code>const UncontrolledForm = () =&gt; {\n    const inputRef = React.createRef&lt;HTMLInputElement&gt;()           -----------------  \uff11\n    const handleSubmit = event =&gt; {\n        event.preventDefault();\n        console.log(inputRef.current.value);                       -----------------  \uff13\n    }\n    return (\n        &lt;&gt;\n            &lt;div&gt;\n                &lt;input ref={inputRef} type=&quot;text&quot; name=&quot;name&quot; \/&gt;   -----------------  \uff12\n                &lt;button onClick={handleSubmit} &gt;Submit&lt;\/button&gt;\n            &lt;\/div&gt;\n        &lt;\/&gt;\n    );\n}<\/code><\/pre>\n<p>Uncontrolled Component \u306f DOM \u3067\u30e6\u30fc\u30b6\u306e\u5165\u529b\u3057\u3066\u3044\u308b\u5024\u3092\u7ba1\u7406\u3059\u308b<br \/>\n\u7c21\u5358\u306a3\u3064\u306e\u30b9\u30c6\u30c3\u30d7\u3067\u304b\u3051\u308b<\/p>\n<ol>\n<li>inputRef \u3068\u3057\u3066 DOM \u30ce\u30fc\u30c9\u3092\u76e3\u8996\u3059\u308b\u305f\u3081\u306e reference \u3092\u4f5c\u6210\u3059\u308b<\/li>\n<li>input \u30bf\u30b0\u306b\u4f5c\u6210\u3057\u305f inputRef \u3092\u767b\u9332\u3057\u3066\u3042\u3052\u308b\n<ul>\n<li>\u3053\u308c\u3067 inputRef \u3092\u901a\u3057\u3066 input \u306b\u30a2\u30af\u30bb\u30b9\u53ef\u80fd<\/li>\n<\/ul>\n<\/li>\n<li>submit \u3092\u62bc\u3057\u305f\u30bf\u30a4\u30df\u30f3\u30b0\u3067 onClick event \u304c\u8d70\u308a\u51fa\u3057, inputRef \u3092\u901a\u3057\u3066\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u5024\u3092\u53d6\u5f97<\/li>\n<\/ol>\n<p>\u3053\u306e\u3088\u3046\u306bref \u3092\u4f5c\u6210, input \u306b\u767b\u9332, \u5165\u529b\u3055\u308c\u3066\u3044\u308b\u5024\u304c\u5fc5\u8981\u306a\u30bf\u30a4\u30df\u30f3\u30b0\u3067 DOM \u304b\u3089\u53d6\u308a\u51fa\u3059<br \/>\n\u3068\u3044\u3046\u6d41\u308c\u306b\u306a\u308b<\/p>\n<h3>Uncontrolled Component\u3000\u306e\u30e1\u30ea\u30c3\u30c8, \u30c7\u30e1\u30ea\u30c3\u30c8<\/h3>\n<ul>\n<li>\u30e1\u30ea\u30c3\u30c8\n<ul>\n<li>\u5fc5\u8981\u306a\u30bf\u30a4\u30df\u30f3\u30b0\u3067\u30d5\u30a3\u30fc\u30eb\u30c9\u304b\u3089\u3068\u3063\u3066\u304f\u308b\u3060\u3051\u306a\u306e\u3067\u8efd\u91cf<\/li>\n<li>\u8a18\u8ff0\u91cf\u304c\u5c11\u306a\u3044\n<ul>\n<li>\u305f\u3060\u3057\u30b7\u30f3\u30d7\u30eb\u306a\u3082\u306e<\/li>\n<\/ul>\n<\/li>\n<li>\u79fb\u690d\u6027\u304c\u9ad8\u3044\n<ul>\n<li>HTML \u30cd\u30a4\u30c6\u30a3\u30d6\u306e\u5b9f\u88c5\u306b\u8fd1\u3044\u306e\u3067\u4ed6\u306e\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u7b49\u3078\u306e\u79fb\u690d\u304c\u5bb9\u6613\u306b\u306a\u308b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\u30c7\u30e1\u30ea\u30c3\u30c8\n<ul>\n<li>\u5fc5\u8981\u306a\u30bf\u30a4\u30df\u30f3\u30b0\u3067\u30d5\u30a3\u30fc\u30eb\u30c9\u304b\u3089\u53d6\u308a\u51fa\u3059\u65b9\u5f0f\u306a\u306e\u3067, \u5165\u529b\u3054\u3068\u306b\u4f55\u304b\u3057\u305f\u3044\u5834\u5408\u306b\u3053\u307e\u308b\n<ul>\n<li>\u5165\u529b\u3054\u3068\u306b validation \u3057\u3066 error \u3092\u8868\u793a\u3059\u308b<\/li>\n<li>\u30e6\u30fc\u30b6\u306e\u5165\u529b\u306b\u5bfe\u3057\u3066\u30b5\u30b8\u30a7\u30b9\u30c8\u3059\u308b\u3088\u3046\u306a\u5834\u5408<\/li>\n<\/ul>\n<\/li>\n<li>\u67d4\u8edf\u6027\u304c\u8584\u3044\n<ul>\n<li>\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u5024\u3092\u5b50\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306b\u308f\u305f\u3059\u5834\u5408<\/li>\n<li>input \u540c\u58eb\u304c\u4f9d\u5b58\u95a2\u4fc2\u3092\u4fdd\u3064\u5834\u5408\n<ul>\n<li>\u3042\u308b\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u304c\u62bc\u3055\u308c\u3066\u308b\u5834\u5408\u306e\u307f\u306b\u51fa\u3066\u304f\u308b\u30d5\u30a3\u30fc\u30eb\u30c9\u7b49<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>Controlled Component<\/h3>\n<p><img src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/react-form-sample.jpg\" alt=\"\" \/><\/p>\n<p>\u5148\u7a0b\u3068\u540c\u3058\u30d5\u30a9\u30fc\u30e0\u3092\u30b3\u30fc\u30c9\u306b\u8d77\u3053\u3057\u3066\u307f\u308b<\/p>\n<pre><code>const ControlledForm = () =&gt; {\n    const [name, setName] = useState(&#039;&#039;);                           ------------------- 1\n    const handleNameChange = (event) =&gt; {\n        setName(event.target.value);\n    };\n    const handleSubmit = () =&gt; {\n        console.log(name);                                          ------------------- 4\n    }\n\n    return (\n        &lt;div&gt;\n            &lt;input type=&quot;text&quot; value={name} onChange={handleNameChange} \/&gt;    --------- 2, 3\n            &lt;button onClick={handleSubmit} &gt;Submit&lt;\/button&gt;\n        &lt;\/div&gt;\n    );\n}<\/code><\/pre>\n<p>Controlled Component \u3067\u306f react \u306e state \u3067\u30e6\u30fc\u30b6\u306e\u5165\u529b\u3057\u3066\u3044\u308b\u5024\u3092\u7ba1\u7406\u3059\u308b<\/p>\n<ol>\n<li>\u5165\u529b\u5024\u7528\u306e state \u3092\u4f5c\u6210<\/li>\n<li>value={name}\n<ul>\n<li>state \u3068\u30d5\u30a9\u30fc\u30e0\u306e\u5165\u529b\u5024 value \u3092\u540c\u671f<\/li>\n<\/ul>\n<\/li>\n<li>onChange={handleNameChange}\n<ul>\n<li>\u30e6\u30fc\u30b6\u304c\u5165\u529b\u3092\u5909\u66f4\u3059\u308b\u305f\u3073\u306b handleNameChange \u3092\u5b9f\u884c\n<ul>\n<li>state \u3092\u30e6\u30fc\u30b6\u306e\u5165\u529b\u5024\u306b\u540c\u671f\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\u5165\u529b\u5024\u304c\u5fc5\u8981\u306a\u30bf\u30a4\u30df\u30f3\u30b0\u3067 state \u304b\u3089\u53d6\u5f97\u3059\u308b<\/li>\n<\/ol>\n<p>Controlled Component \u306f input \u306e change \u30a4\u30d9\u30f3\u30c8\u3067 state \u66f4\u65b0, value \u306b state \u3092\u5165\u308c\u308b\u306e\u304c\u57fa\u672c\u306b\u306a\u308b<\/p>\n<h3>Controlled Component \u306e state \u66f4\u65b0\u306e\u6d41\u308c<\/h3>\n<p><img src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/controlled.jpg\" alt=\"\" \/><\/p>\n<p>\u753b\u50cf\u304c 'dog' \u3068\u30e6\u30fc\u30b6\u304c\u5165\u529b\u3059\u308b\u5834\u5408\u306e\u6d41\u308c\u306b\u306a\u308b<\/p>\n<p>\u6700\u521d state \u306e\u5024\u306f\u3000\u2019\u2019 \u7a7a\u3067\u4f5c\u6210. \u521d\u671f\u5316\u3055\u308c\u308b<br \/>\n\u30e6\u30fc\u30b6\u304c 'd' \u3092\u5165\u529b\u3059\u308b\u3068 change \u30a4\u30d9\u30f3\u30c8\u304c\u8d70\u308a handleNameChange \u306b\u3088\u3063\u3066 state \u304c\u66f4\u65b0\u3055\u308c\u308b<br \/>\nstate \u306e\u66f4\u65b0\u306b\u3088\u3063\u3066 react \u304c\u518d\u30ec\u30f3\u30c0\u30fc\u3092\u884c\u3046<br \/>\n\u6b21\u306b 'o' \u3092\u5165\u529b\u3057\u305f\u30bf\u30a4\u30df\u30f3\u30b0\u3082\u540c\u3058\u4f5c\u696d\u3092\u7e70\u308a\u8fd4\u3057\u518d\u30ec\u30f3\u30c0\u30fc, 'g' \u3092\u5165\u529b\u3057\u30bf\u30a4\u30df\u30f3\u30b0\u3082\u540c\u69d8<\/p>\n<p>\u3068\u3044\u3046\u3088\u3046\u306b state \u304c\u66f4\u65b0\u3055\u308c\u3066\u3044\u304f<br \/>\n\u8a00\u3044\u63db\u3048\u308b\u3068 state \u3068\u5165\u529b\u5024\u306f\u5e38\u306b\u540c\u671f\u3055\u308c\u3066\u3044\u308b\u3068\u3044\u3046\u3053\u3068\u3067\u3042\u308a, \u5165\u529b\u5024\u304c\u5909\u308f\u308b\u305f\u3073\u306b\u518d\u30ec\u30f3\u30c0\u30fc\u3055\u308c\u308b\u3068\u3044\u3046\u3053\u3068\u3067\u3042\u308b<\/p>\n<h3>Controlled Component \u306e\u30e1\u30ea\u30c3\u30c8, \u30c7\u30e1\u30ea\u30c3\u30c8<\/h3>\n<ul>\n<li>\u30e1\u30ea\u30c3\u30c8\n<ul>\n<li>\u5e38\u306b\u5165\u529b\u5024\u3092 state \u306b\u6301\u3063\u3066\u3044\u308b\u3068\u3044\u3046\u3053\u3068\n<ul>\n<li>state \u304c SSOT (Single Source of Truth) \u306b\u306a\u308a, state \u306e\u307f\u4fe1\u7528\u3057\u3066\u304b\u3051\u308b<\/li>\n<li>\u5165\u529b\u3059\u308b\u3054\u3068\u306b\u64cd\u4f5c (validation, error \u8868\u793a\u7b49)\u3092\u3057\u3084\u3059\u3044<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\u30c7\u30e1\u30ea\u30c3\u30c8\n<ul>\n<li>\u5165\u529b\u3059\u308b\u305f\u3073\u306b render \u3055\u308c\u308b\u306e\u3067\u91cd\u3044\n<ul>\n<li>\u7279\u306b\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u30c4\u30ea\u30fc\u306e\u4e0a\u4f4d\u306b\u3042\u308b\u3068\u4e0b\u4f4d\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3082\u518d\u30ec\u30f3\u30c0\u30fc\u3057\u3066\u3057\u307e\u3046<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>\u307e\u3068\u3081<\/h3>\n<ul>\n<li>\n<p>Controlled Component, Uncontrolled Component \u3068\u3082\u306b\u4e00\u9577\u4e00\u77ed\u3067\u3042\u308b<\/p>\n<ul>\n<li>Controlled Component \u306e\u307b\u3046\u304c\u67d4\u8edf\u306b\u3067\u304d\u308b\u304c\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u304c\u4f4e\u3044<\/li>\n<li>Uncontrolled Componentr \u306e\u307b\u3046\u304c\u3067\u304d\u308b\u3053\u3068\u306f\u5c11\u306a\u3044\u304c\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u304c\u9ad8\u3044<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u8003\u3048\u308b\u3053\u3068\u3068\u3057\u3066<\/p>\n<ul>\n<li>Controlled \u306e\u307b\u3046\u304c React \u7684\u306b\u304b\u3051\u308b (state \u3067\u7ba1\u7406)<\/li>\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u8003\u3048\u308b\u3068...\n<ul>\n<li>\u57fa\u672c\u306f\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u304c\u9ad8\u304f\u30b7\u30f3\u30d7\u30eb\u306b\u304b\u3051\u308b Uncontrolled \u3067\u5b9f\u88c5<\/li>\n<li>\u8907\u96d1\u306a\u30d5\u30a9\u30fc\u30e0\u306f Controlled \u3067\u66f8\u304f\u3068\u3044\u3046\u3053\u3068\u3082<br \/>\ne.g. \u5165\u529b\u6bce\u306b validation, \u5165\u529b\u5024\u3092\u5f37\u5236\u3059\u308b, input \u540c\u58eb\u3067\u4f9d\u5b58\u95a2\u4fc2\u7b49<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>React \u3067\u5b9f\u969b\u306b\u30d5\u30a9\u30fc\u30e0\u3092\u66f8\u304f<\/h2>\n<ul>\n<li>\u4e0b\u306e\u3088\u3046\u306a\u30d5\u30a9\u30fc\u30e0\u3092\u5b9f\u88c5\u3057\u3066\u307f\u308b\n<ul>\n<li>input \u306f2\u3064, Name \u3068 Email\n<ul>\n<li>\u305d\u308c\u305e\u308c\u306b\u5165\u529b\u5fc5\u9808\u306e validation, \u5165\u529b\u304c\u306a\u3044\u5834\u5408\u306b\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8868\u793a\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<li>Submit \u30dc\u30bf\u30f3\u304c\u3042\u308a\u62bc\u3059\u3068 console \u306b\u5165\u529b\u5024\u3092\u8868\u793a\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/react-hook-form.jpg\" alt=\"\" \/><\/p>\n<p>\u30b3\u30fc\u30c9\u306b\u8d77\u3053\u3059<br \/>\n(\u4ee5\u4e0b\u3067\u89e3\u8aac\u3059\u308b\u306e\u3067\u305d\u3093\u306a\u306b\u898b\u306a\u304f\u3066 ok \u3067\u3059)<\/p>\n<pre><code>const Form = () =&gt; {\n    const [values, setValues] = useState({\n        name: &#039;&#039;,\n        email: &#039;&#039;\n    });\n\n    const [errors, setErrors] = useState({\n        name: &#039;&#039;,\n        email: &#039;&#039;\n    })\n\n    const handleChange: (name) =&gt; (event) =&gt; void = (name) =&gt; (event) =&gt; {\n        const newValues = {\n            ...values,\n            [name]: event.target.value\n        }\n        setValues(newValues);\n        validate(newValues, name);\n    };\n\n    const validate = (values, name) =&gt; {\n        switch(name) {\n            case &#039;name&#039;:\n                nameValidation(values.name);\n                break;\n            case &#039;email&#039;:\n                emailValidation(values.email);\n                break;\n        }\n    }\n\n    const nameValidation = (value: string): void =&gt; {\n        if (value.length === 0) {\n            setErrors({...errors, name: &#039;\u540d\u524d\u306f1\u6587\u5b57\u4ee5\u4e0a&#039;});\n        }\n        else {\n            setErrors({...errors, name: &#039;&#039;});\n        }\n    }\n\n    const emailValidation = (value: string): void =&gt; {\n        if (value.length === 0) {\n            setErrors({...errors, email: &#039;Email\u306f1\u6587\u5b57\u4ee5\u4e0a&#039;});\n        }\n        else {\n            setErrors({...errors, email: &#039;&#039;});\n        }\n    }\n\n    const handleSubmit = () =&gt; {\n        console.log(values);\n    }\n\n    return (\n        &lt;&gt;\n            &lt;div&gt;\n                &lt;h4&gt;Name: &lt;\/h4&gt;\n                &lt;input type=&quot;text&quot; name=&quot;name&quot; value={values.name} onChange={handleChange(&#039;name&#039;)} \/&gt;\n                { errors.name &amp;&amp; &lt;span className=&quot;text-danger&quot;&gt;{ errors.name }&lt;\/span&gt;}\n                &lt;h4&gt;Email: &lt;\/h4&gt;\n                &lt;input type=&quot;email&quot; name=&quot;email&quot; value={values.email} onChange={handleChange(&#039;email&#039;)} \/&gt;\n                { errors.email &amp;&amp; &lt;span className=&quot;text-danger&quot;&gt;{ errors.email }&lt;\/span&gt;}\n                &lt;div&gt;\n                    &lt;button onClick={handleSubmit} &gt;Submit&lt;\/button&gt;\n                &lt;\/div&gt;\n            &lt;\/div&gt;\n        &lt;\/&gt;\n    );\n}<\/code><\/pre>\n<p>\u7c21\u55ae\u306a\u30d5\u30a9\u30fc\u30e0\u3060\u304c\u968f\u5206\u30b3\u30fc\u30c9\u304c\u9577\u304f\u306a\u3063\u3066\u3057\u307e\u3046<\/p>\n<ul>\n<li>\u30b3\u30fc\u30c9\u3068\u3057\u3066\u306f\n<ul>\n<li>state \u304c2\u3064\n<ul>\n<li>\u5165\u529b\u5024\n<ul>\n<li>name, email \u3092\u6301\u3064\u30aa\u30d6\u30b8\u30a7\u30af\u30c8<\/li>\n<\/ul>\n<\/li>\n<li>\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\n<ul>\n<li>name, email \u3092\u6301\u3064\u30aa\u30d6\u30b8\u30a7\u30af\u30c8<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\u5165\u529b\u5024 state \u66f4\u65b0\u30e1\u30bd\u30c3\u30c9<\/li>\n<li>\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8 state \u66f4\u65b0\u30e1\u30bd\u30c3\u30c9<\/li>\n<li>input \u3054\u3068\u306b validate \u632f\u308a\u5206\u3051\u30e1\u30bd\u30c3\u30c9<\/li>\n<li>\u305d\u308c\u305e\u308c\u306e validation \u30e1\u30bd\u30c3\u30c9<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u3068\u3044\u3046\u3088\u3046\u306b\u7d50\u69cb\u8003\u3048\u308b\u3053\u3068\u304c\u591a\u3044<br \/>\n\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5897\u3048\u308b\u3068\u305d\u306e\u305f\u3073\u306b state, \u30e1\u30bd\u30c3\u30c9\u7b49\u66f8\u304d\u63db\u3048\u308b\u7b87\u6240\u304c\u591a\u3044\u306e\u3067\u8003\u616e\u6f0f\u308c\u3068\u304b\u8d77\u3053\u308a\u305d\u3046<\/p>\n<p>\u7d50\u5c40\u7d20\u306e React \u3060\u3051\u3067\u30d5\u30a9\u30fc\u30e0\u3092\u66f8\u304f\u306e\u306f\u5272\u3068\u5927\u5909\u3068\u3044\u3046\u3053\u3068\u306b<br \/>\n\u7279\u306b GROWI.cloud \u3067\u306f GROWI \u3092\u7acb\u3061\u4e0a\u3052\u308b\u969b\u306e\u5165\u529b\u3059\u308b\u30d1\u30e9\u30e1\u30fc\u30bf\u304c\u591a\u304f, \u4f9d\u5b58\u95a2\u4fc2\u3082\u3042\u308b<br \/>\n\u305d\u3053\u3067 React Hook Form \u3092\u5c0e\u5165\u3057\u3066\u307f\u308b<\/p>\n<h2>React Hook Form<\/h2>\n<p><a href=\"https:\/\/react-hook-form.com\/\">React Hook Form<\/a><\/p>\n<p>v7.13.0 \u3067\u8aac\u660e\u3057\u307e\u3059<\/p>\n<h3>\u3069\u3046\u3044\u3046\u30e9\u30a4\u30d6\u30e9\u30ea<\/h3>\n<p>React \u7528\u30d5\u30a9\u30fc\u30e0\u30e9\u30a4\u30d6\u30e9\u30ea<\/p>\n<p>\u7279\u5fb4\u306f<\/p>\n<ul>\n<li>\u8a18\u8ff0\u304c\u5c11\u306a\u304f, \u30b7\u30f3\u30d7\u30eb\n<ul>\n<li>\u7279\u306b\u30e9\u30a4\u30d6\u30e9\u30ea\u306b\u5bc4\u305b\u305f\u66f8\u304d\u65b9\u3092\u3059\u308b\u3068\u304b\u306a\u308a\u30b7\u30f3\u30d7\u30eb\u306b\u304b\u3051\u308b<\/li>\n<\/ul>\n<\/li>\n<li>\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u304c\u5c11\u306a\u304f, \u30de\u30a6\u30f3\u30c8\u304c\u65e9\u3044\n<ul>\n<li>Uncontrolled Component \u3092\u30d9\u30fc\u30b9\u306b\u4f5c\u3089\u308c\u3066\u3044\u308b<\/li>\n<li>\u4ed6\u306e\u30d5\u30a9\u30fc\u30e0\u30e9\u30a4\u30d6\u30e9\u30ea\u3068\u6bd4\u3079\u3066\u304b\u306a\u308a\u65e9\u3044<\/li>\n<\/ul>\n<\/li>\n<li>\u30d1\u30c3\u30b1\u30fc\u30b8\u304c\u5c0f\u3055\u304f\u8efd\u91cf\n<ul>\n<li>\u4f9d\u5b58\u30d1\u30c3\u30b1\u30fc\u30b8 0<\/li>\n<\/ul>\n<\/li>\n<li>\u30ea\u30ea\u30fc\u30b9\u304c\u304b\u306a\u308a\u983b\u7e41\u306b\u3055\u308c\u3066\u3044\u308b<\/li>\n<\/ul>\n<h3>\u5c0e\u5165<\/h3>\n<ul>\n<li><code>yarn add react-hook-form<\/code>\n<ul>\n<li>yarn add \u6253\u3064\u3060\u3051<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>\u30b3\u30fc\u30c9\u304b\u3089\u4f7f\u3044\u65b9\u3092\u898b\u308b<\/h3>\n<p>\u4ee5\u4e0b\u306e\u3055\u3063\u304d\u3068\u540c\u3058\u30d5\u30a9\u30fc\u30e0\u3092 react-hook-form \u3067\u66f8\u3044\u3066\u307f\u308b<\/p>\n<p><img src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/react-hook-form.jpg\" alt=\"\" \/><\/p>\n<pre><code>const Form = () =&gt; {\n  const { register, handleSubmit, formState: { errors } } = useForm();           -------------- 1\n  const onSubmit = data =&gt; { console.log(data) }                                 -------------- 3\n\n  return (\n    &lt;form onSubmit={handleSubmit(onSubmit)}&gt;\n        &lt;h4&gt;Name: &lt;\/h4&gt;\n        &lt;input {...register(&#039;name&#039;, { required: true })} \/&gt;                      -------------- 2\n        { errors.name &amp;&amp; &lt;span className=&quot;text-danger&quot;&gt;\u540d\u524d\u306f1\u6587\u5b57\u4ee5\u4e0a&lt;\/span&gt; }    ---------------4\n        &lt;h4&gt;Email: &lt;\/h4&gt;\n        &lt;input { ...register(&#039;email&#039;, { required: true })} \/&gt;                     -------------- 2\n        { errors.email &amp;&amp; &lt;span className=&quot;text-danger&quot;&gt;Email\u306f1\u6587\u5b57\u4ee5\u4e0a&lt;\/span&gt; }  -------------- 4\n        &lt;div&gt;\n            &lt;input type=&quot;submit&quot; value=&quot;Submit&quot;&gt;&lt;\/input&gt;\n        &lt;\/div&gt;\n    &lt;\/form&gt;\n  )\n}<\/code><\/pre>\n<p>\u307e\u305a\u30b3\u30fc\u30c9\u304c\u304b\u306a\u308a\u7c21\u7d20\u5316\u3055\u308c\u305f\u306e\u304c\u308f\u304b\u308b<br \/>\nstate \u306e\u7ba1\u7406\u304c\u306a\u304f\u306a\u3063\u3066\u3044\u308b<\/p>\n<p>react-hook-form \u306e\u57fa\u672c\u7684\u306a\u4f7f\u3044\u65b9\u3092\u30b3\u30fc\u30c9\u304b\u3089\u898b\u308b<\/p>\n<ol>\n<li>react-hook-form \u306e\u63d0\u4f9b\u3059\u308b <a href=\"https:\/\/react-hook-form.com\/api\/useform\">userForm()<\/a> \u304b\u3089\u5fc5\u8981\u306a\u30e1\u30bd\u30c3\u30c9, \u30aa\u30d6\u30b8\u30a7\u30af\u30c8 (\u5f8c\u8ff0) \u3092\u53d6\u5f97<\/li>\n<li>input \u30bf\u30b0\u3078\u53d6\u5f97\u3057\u305f register \u3092\u767b\u9332\n<ul>\n<li>register \u306b ref \u304c\u5165\u3063\u3066\u3044\u308b\u306e\u3067 input \u3092\u76e3\u8996\u3067\u304d\u308b<\/li>\n<li>register \u306e\u5f15\u6570\u306b\u76e3\u8996\u7528\u306e name , validation \u306e\u30eb\u30fc\u30eb\u3092\u767b\u9332<\/li>\n<\/ul>\n<\/li>\n<li>Submit \u30dc\u30bf\u30f3\u3092\u62bc\u3057\u305f\u969b\u306e\u6319\u52d5\u3092\u767b\u9332<\/li>\n<li>validation \u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u3068 useForm() \u304b\u3089\u53d6\u5f97\u3057\u3066\u3044\u308b errors \u306b\u5165\u3063\u3066\u304f\u308b\u306e\u3067, \u3042\u308b\u5834\u5408\u306f\u30a8\u30e9\u30fc\u8868\u793a<\/li>\n<\/ol>\n<p>\u57fa\u672c\u7684\u306b\u306f, useForm() \u304b\u3089 register \u3068\u305d\u306e\u4ed6\u5fc5\u8981\u306a\u30e1\u30bd\u30c3\u30c9, \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u53d6\u5f97<br \/>\nreact-hook-form \u3067\u76e3\u8996\u3059\u308b input \u3078 register \u3092\u767b\u9332<br \/>\nuseForm() \u306e\u30e1\u30bd\u30c3\u30c9, \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u3088\u3057\u306a\u306b\u4f7f\u3046<br \/>\n\u3068\u3044\u3046\u6d41\u308c\u306b\u306a\u308b<\/p>\n<h4>FormBuilder<\/h4>\n<p>react-hook-form \u3067\u306f\u516c\u5f0f\u306b form \u3092\u7c21\u5358\u306b\u3064\u304f\u308c\u308b FormBilder \u3068\u3044\u3046\u3082\u306e\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u308b\u306e\u3067\u3064\u3044\u3067\u306b\u7d39\u4ecb<\/p>\n<p><a href=\"https:\/\/react-hook-form.com\/form-builder\">https:\/\/react-hook-form.com\/form-builder<\/a><\/p>\n<p>\u30d6\u30e9\u30a6\u30b6\u4e0a\u3067\u30d5\u30a9\u30fc\u30e0\u306e\u30ec\u30a4\u30a2\u30a6\u30c8\u3084\u57fa\u672c\u7684\u306a validation \u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u3067\u305d\u308c\u306b\u3042\u3063\u305f\u30b3\u30fc\u30c9\u304c\u751f\u6210\u3055\u308c\u308b<\/p>\n<h3>useForm()<\/h3>\n<p>\u57fa\u672c\u7684\u306b\u306f<a href=\"https:\/\/react-hook-form.com\/api\/useform\">\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8<\/a>\u306b\u304b\u3044\u3066\u3042\u308b<\/p>\n<p>useForm() \u306f\u5f15\u6570\u3092\u53d6\u308b\u3053\u3068\u304c\u3067\u304d\u3066, \u8fd4\u3059\u30e1\u30bd\u30c3\u30c9, \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3082\u4fbf\u5229\u306a\u3082\u306e\u304c\u591a\u3044\u306e\u3067\u3044\u304f\u3064\u304b\u7d39\u4ecb<br \/>\n\u4ee5\u4e0b\u306f\u7d39\u4ecb\u3059\u308b\u3082\u306e\u3092\u8a18\u8ff0\u3057\u305f\u3082\u306e<\/p>\n<pre><code>useForm({\n    mode: &#039;onChange&#039;,\n    defaultValues: {\n        name: &#039;defaultName&#039;,\n        email: &#039;defaultEmail&#039;,\n    },\n    shouldUnregister: false\n})\n<\/code><\/pre>\n<ul>\n<li>\u5f15\u6570\n<ul>\n<li>mode (\u4e00\u90e8)\n<ul>\n<li>onChange\n<ul>\n<li>\u30e6\u30fc\u30b6\u306e\u5165\u529b\u6bce\u306b register \u3067\u767b\u9332\u3057\u305f validation \u3092\u5b9f\u884c\u3059\u308b<\/li>\n<li>\u5185\u90e8\u3067 state \u3092\u4f7f\u308f\u306a\u3044\u306e\u3067 validation \u306e\u7d50\u679c\u304c\u5909\u308f\u308b\u307e\u3067\u518d render \u3055\u308c\u306a\u3044<\/li>\n<\/ul>\n<\/li>\n<li>onSubmit\n<ul>\n<li>submit \u6642\u306b validation \u3092\u5b9f\u884c<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>defaultValues\n<ul>\n<li>register \u6642\u306b\u767b\u9332\u3057\u305f name \u3067\u5404 input \u306e\u5024\u3092\u4e00\u5143\u7ba1\u7406\u304c\u3067\u304d\u308b<\/li>\n<li>\u6700\u521d\u306b render \u3057\u305f\u3068\u304d\u306e\u5024\u306a\u306e\u3067\u518d\u5ea6 defaultValues \u306b\u623b\u3057\u305f\u3044\u5834\u5408\u7b49\u306f\u5225\u9014\u306b resetAPI(\u5f8c\u8ff0) \u3092\u53e9\u304f\u5fc5\u8981\u304c\u3042\u308b<\/li>\n<\/ul>\n<\/li>\n<li>shouldUnregister\n<ul>\n<li>input \u304c\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u304b\u3089\u6d88\u3048\u305f\u30bf\u30a4\u30df\u30f3\u30b0\u3067 unregister \u3059\u308b\u304b\u3069\u3046\u304b<\/li>\n<li>unregister \u3059\u308b\u3068 input \u306e\u72b6\u614b(\u5165\u529b\u5024\u7b49) \u304c\u518d\u5ea6 input \u304c render \u3055\u308c\u305f\u3068\u304d\u306b\u5f15\u304d\u7d99\u304c\u308c\u306a\u3044<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\u30e1\u30bd\u30c3\u30c9, \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\n<ul>\n<li>register\n<ul>\n<li>input \u3078\u767b\u9332\u3059\u308b\u3082\u306e<\/li>\n<li>Reference \u3068 validation rule\u306e\u767b\u9332, \u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u767b\u9332\u3059\u308b\u3053\u3068\u3082\u3067\u304d\u308b<\/li>\n<li>validation \u306b\u306f HTML \u6a19\u6e96\u306e rule, \u81ea\u524d\u306e\u30e1\u30bd\u30c3\u30c9\u3082\u767b\u9332\u3067\u304d\u308b<\/li>\n<\/ul>\n<\/li>\n<li>errors\n<ul>\n<li>register \u6642\u306b\u767b\u9332\u3057\u305f validation \u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u3068\u3053\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b error \u306e input \u304c\u5165\u308b<\/li>\n<\/ul>\n<\/li>\n<li>reset\n<ul>\n<li>\u30d5\u30a9\u30fc\u30e0\u306e\u5024\u3092 defaultValues \u306b\u623b\u3059<\/li>\n<li>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u5f15\u6570\u306b\u308f\u305f\u3059\u3053\u3068\u3067 values \u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u3082\u3067\u304d\u308b<\/li>\n<\/ul>\n<\/li>\n<li>watch\n<ul>\n<li>\u6307\u5b9a\u3057\u305f input\/inputs \u3092\u76e3\u8996\u3059\u308b<\/li>\n<li>readonly \u306a\u5165\u529b\u5024\u306e state \u307f\u305f\u3044\u306a\u3082\u306e\u3067\u3053\u308c\u3092\u4f7f\u3046\u5834\u5408\u518d\u30ec\u30f3\u30c0\u30fc\u3055\u308c\u308b<\/li>\n<\/ul>\n<\/li>\n<li>getValues\n<ul>\n<li>\u30d5\u30a9\u30fc\u30e0\u306e\u5024\u3092\u53d6\u5f97<\/li>\n<\/ul>\n<\/li>\n<li>trigger\n<ul>\n<li>\u624b\u52d5 validation \u5b9f\u884c\u30e1\u30bd\u30c3\u30c9<\/li>\n<\/ul>\n<\/li>\n<li>formState\n<ul>\n<li>isDirty, isValid, isSubmitted \u7b49\u306e\u30d5\u30a9\u30fc\u30e0\u306e\u72b6\u614b\u3092\u6301\u3064<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>\u5b9f\u969b\u306e <a href=\"https:\/\/growi.cloud\/\">GROWI.cloud<\/a> \u3067\u306e\u4f7f\u3044\u65b9<\/h2>\n<p>\u57fa\u672c\u7684\u306a\u4f7f\u3044\u65b9\u306f\u524d\u8ff0\u306e\u901a\u308a, \u5b9f\u969b\u306b <a href=\"https:\/\/growi.cloud\/\">GROWI.cloud<\/a> \u3067\u4f7f\u3063\u3066\u3044\u3066, \u5c11\u3057\u56f0\u3063\u305f\u5834\u9762\u3084\u305d\u306e\u5bfe\u51e6\u306b\u3064\u3044\u3066<\/p>\n<h3>\u30cd\u30b9\u30c8\u3057\u305f\u30d5\u30a9\u30fc\u30e0\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8<\/h3>\n<h4>\u30cd\u30b9\u30c8\u3057\u305f\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3068\u306f<\/h4>\n<p>Input \u304c\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u4e2d\u306b\u3044\u3066\u30cd\u30b9\u30c8\u3057\u3066\u3044\u308b\u5834\u5408<\/p>\n<p>\u4f8b\u3048\u3070\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u69cb\u6210<\/p>\n<pre><code>&lt;form onSubmit={handleSubmit(onSubmit)}&gt;\n  &lt;NestedInputA&gt;&lt;NestedInputA \/&gt;\n  &lt;NestedInputB&gt;&lt;NestedInputB \/&gt;\n  &lt;input type=&quot;submit&quot; value=&quot;Submit&quot;&gt;&lt;\/input&gt;\n&lt;\/form&gt;<\/code><\/pre>\n<p>NestedInputA\/B \u306f\u305d\u308c\u305e\u308c input \u30bf\u30b0\u3092\u5185\u90e8\u306b\u6301\u3063\u3066\u3044\u308b<br \/>\nuseForm() \u304b\u3089\u53d6\u5f97\u3057\u305f\u3082\u306e\u3092\u4e0b\u4f4d\u306e input \u3078\u6e21\u3059\u5fc5\u8981\u304c\u3042\u308b<br \/>\n\u5358\u7d14\u306a\u5b9f\u88c5\u3060\u3068\u4ee5\u4e0b\u306b\u306a\u308b<\/p>\n<pre><code>&lt;form onSubmit={handleSubmit(onSubmit)}&gt;\n  &lt;NestedInputA register={register} errors={errors}&gt;&lt;\/NestedFormA&gt;\n  &lt;NestedInputB register={register} errors={errors}&gt;&lt;\/NestedFormB&gt;\n  &lt;input type=&quot;submit&quot; value=&quot;Submit&quot;&gt;&lt;\/input&gt;\n&lt;\/form&gt;<\/code><\/pre>\n<p>useForm() \u304b\u3089\u53d6\u5f97\u3057\u305f\u3082\u306e\u3092 props \u3068\u3057\u3066\u4e0b\u4f4d\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306b\u6e21\u3057\u3066\u3044\u308b<\/p>\n<ul>\n<li>\u3057\u304b\u3057\u3053\u308c\u3060\u3068\u5197\u9577\u3055\u304c\u3042\u3063\u3066\u56f0\u308b\n<ul>\n<li>useForm() \u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u6bce\u56de\u6e21\u3055\u306a\u3044\u3068\u3044\u3051\u306a\u3044<\/li>\n<li>input \u304c\u5b50\u3088\u308a\u4e0b\u306b\u3042\u3063\u305f\u5834\u5408\u3055\u3089\u306b\u305d\u306e\u5b50\u306b\u6e21\u3057\u305f\u308a\u3068\u826f\u304f\u306a\u3044\u30d0\u30b1\u30c4\u30ea\u30ec\u30fc<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4><a href=\"https:\/\/react-hook-form.com\/api\/useformcontext\">useFormContext()<\/a><\/h4>\n<ul>\n<li><a href=\"https:\/\/react-hook-form.com\/api\/useformcontext\">useFormContext()<\/a> \u3092\u4f7f\u3046\u3053\u3068\u3067\u89e3\u6c7a\n<ul>\n<li>react hook \u306e useContext() \u306e\u3088\u3046\u306a\u3082\u306e\u304c\u4f5c\u308c\u308b<\/li>\n<li>\u30cd\u30b9\u30c8\u3057\u305f\u30c4\u30ea\u30fc\u306b context \u3092\u4f5c\u308c\u3066, \u5b50\u304b\u3089\u76f4\u63a5 useForm() \u3092\u53d6\u5f97\u3059\u308b\u4e8b\u304c\u3067\u304d\u308b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u4ee5\u4e0b\u306f\u305d\u306e\u30b3\u30fc\u30c9<\/p>\n<ul>\n<li>\u89aa\n<pre><code>const Parent = () =&gt; {\nconst methods = useForm();\nreturn (\n&lt;FormProvider {...methods}&gt;\n    &lt;form onSubmit={methods.handleSubmit(onSubmit)}&gt;\n        &lt;NestedInputA&gt;&lt;\/NestedInputA&gt;\n        &lt;NestedInputB&gt;&lt;\/NestedInputB&gt;\n    &lt;\/form&gt;\n&lt;\/FormProvider&gt;)\n}<\/code><\/pre>\n<\/li>\n<li>\u5b50\n<pre><code>const NestedChild = () =&gt; {\nconst { register, formState: { errors }} = useFormContext();\nreturn (\n&lt;&gt;\n    &lt;input {...register(&#039;name&#039;, { required: true })} \/&gt;\n    {errors.name &amp;&amp; &lt;span className=&quot;text-danger&quot;&gt;validation error&lt;\/span&gt;}\n&lt;\/&gt;\n}<\/code><\/pre>\n<\/li>\n<\/ul>\n<p>\u7c21\u5358\u306a\u89e3\u8aac<\/p>\n<ul>\n<li>\u89aa\n<ul>\n<li><code>&lt;FormProvider&gt;<\/code> \u3067\u56f2\u3046\u3053\u3068\u3067 context \u3092\u4f5c\u308b<\/li>\n<li><code>&lt;FormProvider&gt;<\/code> \u306b\u306f useForm() \u304b\u3089\u53d6\u5f97\u3057\u305f\u30e1\u30bd\u30c3\u30c9, \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u6e21\u3059<\/li>\n<\/ul>\n<\/li>\n<li>\u5b50\n<ul>\n<li>\u4eca\u307e\u3067 useForm() \u304b\u3089\u53d6\u5f97\u3057\u3066\u3044\u305f\u3082\u306e\u3092\u540c\u3058\u3088\u3046\u306a\u65b9\u6cd5\u3067 useFormContext() \u304b\u3089\u53d6\u5f97\u3059\u308b<\/li>\n<li>\u540c\u3058\u3088\u3046\u306b\u5b50\u4f9b\u3067\u306f\u4f7f\u3048\u308b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>\u3046\u308c\u3057\u3044\u3068\u3053\u308d<\/h4>\n<ul>\n<li>useFormContext() \u3092\u4f7f\u3046\u3053\u3068\u3067\u89aa\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3067 input \u3092\u7ba1\u7406\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u3063\u305f\n<ul>\n<li>defaultValues \u7b49\u3082 useFormContext() \u3078\u6e21\u305b\u308b<\/li>\n<li>useForm() \u306e\u30d0\u30b1\u30c4\u30ea\u30ec\u30fc\u3092\u3057\u306a\u304f\u3066\u826f\u304f\u306a\u3063\u305f<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>\u3053\u308c\u3067\u3082\u5c11\u3057\u56f0\u3063\u305f\u3053\u3068\u304c<\/h4>\n<p>input \u3078\u306e register \u3059\u308b name \u304c\u88ab\u308b\u3068\u3044\u3046\u554f\u984c<br \/>\nname \u306b\u3088\u3063\u3066 input \u3092\u533a\u5225\u3057\u3066\u3044\u308b\u306e\u3067\u4e0a\u624b\u304f\u52d5\u304b\u306a\u3044<\/p>\n<ul>\n<li>\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u69cb\u6210\u3067 input \u306e name \u304c\u304b\u3076\u3063\u3066\u3057\u307e\u3046\n<ul>\n<li>\u4f8b\u3048\u3070\u540c\u3058\u3088\u3046\u306a input \u3092\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3068\u3057\u3066\u5171\u901a\u5316\u3057\u305f\u5834\u5408\u306a\u3069\u306b\u8d77\u3053\u308b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<pre><code>const Parent = () =&gt; {\n  const methods = useForm();\n  return (\n  &lt;&gt;\n    &lt;FormProvider {...methods1}&gt;\n      &lt;ChildInput&gt;&lt;\/ChildInput&gt;\n      &lt;ChildInput&gt;&lt;\/ChildInput&gt;\n    &lt;\/FormProvider&gt;\n  &lt;\/&gt;\n  )}<\/code><\/pre>\n<ul>\n<li>\u306a\u305c\u8d77\u3053\u308b\u304b\n<ul>\n<li>\u5b50\u4f9b\u3067\u76f4\u63a5 input \u306e name \u3092\u3057\u3066\u3044\u308b\u304b\u3089<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u4ee5\u4e0b\u306e\u30b3\u30fc\u30c9\u306e\u3088\u3046\u306b\u5bfe\u51e6\u3057\u3066\u3044\u308b<\/p>\n<pre><code>const Parent = () =&gt; {\n  const inputName1 = \u2018name\u2019;\n  const inputName2 = \u2018email\u2019;\n  const methods = useForm();\n  return (\n  &lt;&gt;\n    &lt;FormProvider {...methods1}&gt;\n      &lt;ChildInput inputName={inputName1}&gt;&lt;\/ChildInput&gt;\n      &lt;ChildInput inputName={inputName2}&gt;&lt;\/ChildInput&gt;\n    &lt;\/FormProvider&gt;\n  &lt;\/&gt;\n  )}<\/code><\/pre>\n<p>name \u3092\u89aa\u3067\u4f5c\u6210\u3057, \u5b50\u306b\u6e21\u3057\u3066\u3042\u3052\u308b\u3053\u3068\u3067\u5bfe\u51e6\u3057\u3066\u3044\u308b<\/p>\n<h3>\u30b5\u30fc\u30d0\u30b5\u30a4\u30c9 validation<\/h3>\n<p>form \u306e validation \u3092\u30b5\u30fc\u30d0\u30b5\u30a4\u30c9\u306b\u3042\u308b API \u3092\u53e9\u304f\u3053\u3068\u3067\u884c\u3044\u305f\u3044<\/p>\n<h4>\u30b5\u30fc\u30d0\u30b5\u30a4\u30c9 validation \u306e\u66f8\u304d\u65b9<\/h4>\n<ul>\n<li>\n<p>async \u95a2\u6570\u81ea\u4f53\u306f\u666e\u901a\u306b\u304b\u3051\u308b<\/p>\n<ul>\n<li><code>&lt;input {...register(&#039;name&#039;, { validate: callValidateAPI})} \/&gt;<\/code><\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u3057\u304b\u3057 useForm() \u3067 mode: onChange \u3092\u6307\u5b9a\u3057\u305f\u3068\u304d\u306b\u5c11\u3057\u5acc\u306a\u3053\u3068\u304c<\/p>\n<ul>\n<li>\u30e6\u30fc\u30b6\u304c\u5165\u529b\u3059\u308b\u305f\u3073\u306b validation API \u3092\u53e9\u304f\u3053\u3068\u306b\u306a\u308b\u306e\u3067, \u30b5\u30fc\u30d0\u306b\u4f59\u5206\u306a\u8ca0\u8377\u304c\u304b\u304b\u308b\n<ul>\n<li>\u30e6\u30fc\u30b6\u304c\u5165\u529b\u3092\u6b62\u3081\u305f\u30bf\u30a4\u30df\u30f3\u30b0\u3067\u9001\u308b\u304f\u3089\u3044\u3067\u826f\u304f\u3066, \u5b9f\u969b\u306b\u306f\u305d\u3053\u307e\u3067\u6bce\u56de\u9001\u3089\u306a\u304f\u3066\u3082\u826f\u3044<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>debounce \u306e\u5c0e\u5165\u3092\u3057\u305f<\/h4>\n<p>debounce \u51e6\u7406\u81ea\u4f53\u306f<a href=\"https:\/\/www.npmjs.com\/package\/throttle-debounce\">\u30e9\u30a4\u30d6\u30e9\u30ea<\/a>\u4f7f\u7528<\/p>\n<h5>debounce\u3068\u306f<\/h5>\n<ul>\n<li>\u3042\u308b\u95a2\u6570\u3092\u6307\u5b9a\u6642\u9593\u4e2d, \u6700\u5f8c\u306e1\u56de\u3060\u3051\u5b9f\u884c\u3059\u308b\n<ul>\n<li>\u95a2\u6570\u306e\u5b9f\u884c\u3092\u9593\u5f15\u304f\u3053\u3068\u304c\u3067\u304d\u308b<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<pre><code>import callValidateAPI from &#039;.\/callValidateAPI&#039;;\n\nconst Input = () =&gt; {\n    conse { register } = useFormContext();\n    const debouncedValidate = debounce(200, callValidateAPI);\n    return (\n        &lt;input {...register(&#039;props.inputName&#039;, { validate: debouncedValidate })} \/&gt;\n    );\n}<\/code><\/pre>\n<p>\u4e0a\u8a18\u306e\u3088\u3046\u306a\u30b3\u30fc\u30c9\u3067200ms \u306b\u8907\u6570\u56de\u9001\u3089\u306a\u3044\u3088\u3046\u306b\u9593\u5f15\u304f\u3053\u3068\u304c\u3067\u304d\u308b<\/p>\n<h4>\u518d\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u3055\u308c\u308b\u5834\u5408<\/h4>\n<ul>\n<li>\u305f\u3060\u3057\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u30d5\u30a9\u30fc\u30e0\u3067\u5c11\u3057\u554f\u984c\u304c\n<ul>\n<li>\u540d\u524d\u3092\u5165\u529b\u3059\u308b\u3068\u73fe\u5728\u306e\u5165\u529b\u5024\u304c\u4e0b\u306b\u3067\u308b\u3088\u3046\u306a\u30d5\u30a9\u30fc\u30e0<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img src=\"https:\/\/weseek.co.jp\/tech\/wp-content\/uploads\/2021\/09\/debounce.jpg\" alt=\"\" \/><\/p>\n<p>\u4e0b\u306b\u8868\u793a\u3059\u308b\u3082\u306e\u3092 useForm() \u306e <a href=\"https:\/\/react-hook-form.com\/api\/useform\/watch\">watch<\/a> \u306b\u3088\u3063\u3066\u5b9f\u73fe\u3057\u3066\u3044\u308b<\/p>\n<ul>\n<li>watch \u3092\u4f7f\u3046\u3053\u3068\u306b\u3088\u3063\u3066\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u304c\u518d\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u3055\u308c\u308b\n<ul>\n<li>debounce \u95a2\u6570\u304c\u518d\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u306b\u3088\u3063\u3066\u5225\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3068\u3057\u3066\u6271\u308f\u308c\u308b\n<ul>\n<li>state, watch \u7b49\u3067\u7ba1\u7406\u3059\u308b\u3068 debounce \u304c\u601d\u3046\u3088\u3046\u306b\u52d5\u304b\u306a\u3044<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u4ee5\u4e0b\u89e3\u6c7a\u3057\u3066\u3044\u308b\u30b3\u30fc\u30c9<\/p>\n<pre><code>import callValidateAPI from &#039;.\/callValidateAPI&#039;;\n\nconst Input = () =&gt; {\n    conse { register } = useFormContext();\n    const debouncedValidate = React.useCallback(debounce(200, callValidateAPI), []);\n    return (\n        &lt;input {...register(&#039;props.inputName&#039;, { validate: debouncedValidate })} \/&gt;\n    );\n}<\/code><\/pre>\n<p>useCallback \u306b debounce \u3057\u3066\u3044\u308b\u95a2\u6570\u3092\u6e21\u3057, \u56fa\u5b9a\u3059\u308b\u3053\u3068\u3067(\u66ab\u5b9a\u306b)\u5bfe\u51e6\u3057\u3066\u3044\u308b<\/p>\n<h3>\u5916\u90e8\u30e9\u30a4\u30d6\u30e9\u30ea\u3068\u306e\u9023\u643a<\/h3>\n<ul>\n<li>react-hook-form \u3067\u7ba1\u7406\u3059\u308b input \u306b\u5916\u90e8\u306e UI \u30e9\u30a4\u30d6\u30e9\u30ea\u7b49\u3092\u4f7f\u3044\u305f\u3044\u5834\u5408\u304c\u3042\u308b\n<ul>\n<li>\u5916\u90e8\u306e\u30e9\u30a4\u30d6\u30e9\u30ea\u304c uncontrolled \u3067\u306a\u3044\u5834\u5408\u7b49\u306f ref \u306b\u767b\u9332\u3067\u304d\u306a\u3044\u306e\u3067\u4eca\u307e\u3067\u8aac\u660e\u3057\u305f\u65b9\u6cd5\u3067\u306f\u3067\u304d\u306a\u3044<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4><a href=\"https:\/\/react-hook-form.com\/api\/usecontroller\/controller\">controller<\/a><\/h4>\n<p>react-hook-form \u306e\u63d0\u4f9b\u3059\u308b <a href=\"https:\/\/react-hook-form.com\/api\/usecontroller\/controller\">controller<\/a> \u3092\u4f7f\u3046\u3053\u3068\u3067\u53ef\u80fd<\/p>\n<p>\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u30b3\u30fc\u30c9\u306b\u306a\u308b<\/p>\n<pre><code>&lt;Controller\n    name=&quot;name&quot;\n    control={control}\n    rules={required: true}\n    render={({onChange, onBlur, value}) =&gt; {\n        &lt;CustomInput\n            value={value}\n            onBlur={onBlur}\n            onChange={onChange}\n        \/&gt;\n    }}\n>\n&lt;\/Controller&gt;<\/code><\/pre>\n<ul>\n<li>useForm() \u304b\u3089\u53d7\u3051\u53d6\u308b control \u3092\u767b\u9332\u3059\u308b\u3053\u3068\u3067 react-hook-form \u306b\u3088\u308b\u7ba1\u7406<\/li>\n<li>rules \u306b\u306f register \u306b\u6e21\u3059 validation \u3068\u540c\u69d8\u306e\u65b9\u6cd5\u3067\u8a18\u8ff0<\/li>\n<\/ul>\n<h3>react-hook-form \u306e\u30c6\u30b9\u30c8<\/h3>\n<p><a href=\"https:\/\/react-hook-form.com\/advanced-usage#TestingForm\">https:\/\/react-hook-form.com\/advanced-usage#TestingForm<\/a><\/p>\n<blockquote>\n<p>We recommend using testing-library, because it is simple and tests are more focused on user behavior.<\/p>\n<\/blockquote>\n<p>react-hook-form \u3067\u306f <a href=\"https:\/\/testing-library.com\/docs\/\">testing-library<\/a> \u3092\u63a8\u5968\u3057\u3066\u3044\u308b\u306e\u3067\u8efd\u304f\u7d39\u4ecb<\/p>\n<p>\u57fa\u672c\u7684\u306b\u306f testing-library \u306b\u5247\u3063\u3066\u884c\u3046<\/p>\n<ul>\n<li>\u6ce8\u610f\u70b9\n<ul>\n<li>handleSubmit \u304c\u975e\u540c\u671f\u306a\u306e\u3067 Submit \u5f8c\u306e\u30c6\u30b9\u30c8\u306b WaitFor, FindBy \u3092\u4f7f\u7528<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u516c\u5f0f\u304b\u3089\u629c\u7c8b<\/p>\n<ul>\n<li>\u30c6\u30b9\u30c8\u5bfe\u8c61\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8<\/li>\n<\/ul>\n<pre><code>import React from &quot;react&quot;;\nimport { useForm } from &quot;react-hook-form&quot;;\n\nexport default function App({ login }) {\n  const { register, handleSubmit, formState: { errors }, reset } = useForm();\n  const onSubmit = async data =&gt; {\n    await login(data.email, data.password);\n    reset();\n  };\n\n  return (\n    &lt;form onSubmit={handleSubmit(onSubmit)}&gt;\n      &lt;label htmlFor=&quot;email&quot;&gt;email&lt;\/label&gt;\n      &lt;input\n        id=&quot;email&quot;\n        {...register(&quot;email&quot;, {\n          required: &quot;required&quot;,\n          pattern: {\n            value: \/\\S+@\\S+\\.\\S+\/,\n            message: &quot;Entered value does not match email format&quot;\n          }\n        })}\n        type=&quot;email&quot;\n      \/&gt;\n      {errors.email &amp;&amp; &lt;span role=&quot;alert&quot;&gt;{errors.email.message}&lt;\/span&gt;}\n      &lt;label htmlFor=&quot;password&quot;&gt;password&lt;\/label&gt;\n      &lt;input\n        id=&quot;password&quot;\n        {...register(&quot;password&quot;, {\n          required: &quot;required&quot;,\n          minLength: {\n            value: 5,\n            message: &quot;min length is 5&quot;\n          }\n        })}\n        type=&quot;password&quot;\n      \/&gt;\n      {errors.password &amp;&amp; &lt;span role=&quot;alert&quot;&gt;{errors.password.message}&lt;\/span&gt;}\n      &lt;button type=&quot;submit&quot;&gt;SUBMIT&lt;\/button&gt;\n    &lt;\/form&gt;\n  );\n}<\/code><\/pre>\n<ul>\n<li>\n<p>\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u3068\u8aac\u660e (\u7d30\u304b\u3044\u3068\u3053\u306f\u7701\u3044\u3066\u3044\u308b)<\/p>\n<pre><code>const mockLogin = jest.fn((email, password) =&gt; {\nreturn Promise.resolve({ email, password });\n});<\/code><\/pre>\n<pre><code>it(&quot;should display required error when value is invalid&quot;, async () =&gt; {\nfireEvent.submit(screen.getByRole(&quot;button&quot;));\n\nexpect(await screen.findAllByRole(&quot;alert&quot;)).toHaveLength(2);\nexpect(mockLogin).not.toBeCalled();\n});<\/code><\/pre>\n<\/li>\n<li>\n<p>\u4f55\u3082\u305b\u305a submitEvent \u3092\u767a\u706b\u3057\u305f\u3068\u304d\u306b required \u306b\u5f15\u3063\u304b\u304b\u308b\u30c6\u30b9\u30c8<\/p>\n<ul>\n<li>getByRole(&quot;button&quot;) \u3067 submit \u30dc\u30bf\u30f3\u3092\u53d6\u5f97\u3057, submit \u30a4\u30d9\u30f3\u30c8\u3092\u767a\u706b<\/li>\n<li>role=&quot;alert&quot;\u3067\u3042\u308b error message \u304c2\u3064\u3042\u308b\u3053\u3068\u3092\u30c6\u30b9\u30c8<\/li>\n<li>handleSubmit \u306b\u3088\u308a invalid \u6642\u306b\u547c\u3070\u308c\u3066\u3044\u306a\u3044\u3053\u3068\u3092\u30c6\u30b9\u30c8<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u3053\u306e\u3088\u3046\u306b\u307b\u307c\u307b\u307c testing-library \u3067\u5b9f\u73fe<\/p>\n<ul>\n<li>\u6b21\u306e\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9 (mockLogin \u306f\u4e0a\u3068\u540c\u3058)<\/li>\n<\/ul>\n<pre><code> it(&quot;should display matching error when email is invalid&quot;, async () =&gt; {\n    fireEvent.input(screen.getByRole(&quot;textbox&quot;, { name: \/email\/i }), {\n      target: {\n        value: &quot;test&quot;\n      }\n    });\n\n    fireEvent.input(screen.getByLabelText(&quot;password&quot;), {\n      target: {\n        value: &quot;password&quot;\n      }\n    });\n\n    fireEvent.submit(screen.getByRole(&quot;button&quot;));\n\n    expect(await screen.findAllByRole(&quot;alert&quot;)).toHaveLength(1);\n    expect(mockLogin).not.toBeCalled();\n    expect(screen.getByRole(&quot;textbox&quot;, { name: \/email\/i }).value).toBe(&quot;test&quot;);\n    expect(screen.getByLabelText(&quot;password&quot;).value).toBe(&quot;password&quot;);\n  });<\/code><\/pre>\n<ul>\n<li>\u540c\u69d8\u306b role \u304b\u3089 input \u3092\u53d6\u5f97\u3057, fireEvent \u306b\u3088\u3063\u3066\u5024\u3092\u66f8\u304d\u63db\u3048\u308b<\/li>\n<li>\u4eca\u56de email \u306e\u5024\u304c invalid \u306a\u306e\u3067 error message 1\u3064\u3067\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u3044\u308b<\/li>\n<\/ul>\n<h2>\u307e\u3068\u3081<\/h2>\n<ul>\n<li>\n<p>(\u7279\u306b\u8907\u96d1\u306a)\u30d5\u30a9\u30fc\u30e0\u306e\u5b9f\u88c5\u306f\u8a2d\u8a08\u3092\u3057\u3063\u304b\u308a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b<\/p>\n<ul>\n<li>\u30d5\u30a9\u30fc\u30e0\u306f\u8003\u3048\u308b\u3053\u3068\u3082\u591a\u304f, \u30e6\u30fc\u30b6\u3068\u5bfe\u8a71\u3059\u308b\u3082\u306e\u306a\u306e\u3067\u91cd\u8981\u3067\u3042\u308b<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>React \u3067\u306e\u30d5\u30a9\u30fc\u30e0\u306b\u306f Uncontrolled Component, Controlled Component \u304c\u3042\u308b<\/p>\n<ul>\n<li>\u305d\u308c\u305e\u308c\u4e00\u9577\u4e00\u77ed\u3067\u3042\u3063\u305f<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u4fbf\u5229\u3055<\/p>\n<ul>\n<li>react-hook-form \u3092\u5165\u308c\u308b\u3053\u3068\u3067\u304b\u306a\u308a\u8a18\u8ff0\u91cf\u304c\u6e1b\u3063\u305f<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>\u8457\u8005\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb<\/h3>\n<p>\u85e4\u6fa4 \u62d3\u4e5f<\/p>\n<p>\u682a\u5f0f\u4f1a\u793eWESEEK \/ \u30b7\u30b9\u30c6\u30e0\u30a8\u30f3\u30b8\u30cb\u30a2<\/p>\n<p>\u5927\u5b66\u3067 Computer Science \u3092\u8efd\u304f\u5b66\u3076. \u5927\u5b66\u5728\u5b66\u6642\u306b WESEEK \u3067\u30a4\u30f3\u30bf\u30fc\u30f3\u3092\u958b\u59cb\u3057, \u305d\u306e\u307e\u307e\u5165\u793e.<br \/>\n\u30a4\u30f3\u30bf\u30fc\u30f3\u958b\u59cb\u3068\u540c\u6642\u306b Web \u958b\u767a\u306b\u521d\u3081\u3066\u643a\u308f\u308b.<\/p>\n<p>\u6700\u521d\u306f\u4e3b\u306b Angular \u3092\u89e6\u3063\u3066, \u6700\u8fd1\u3067\u306f React, Rails, Kubernetes \u7b49\u3044\u308d\u3044\u308d\u624b\u3092\u4ed8\u3051\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059<\/p>\n<h2>\u682a\u5f0f\u4f1a\u793eWESEEK\u306b\u3064\u3044\u3066<\/h2>\n<p><a href=\"https:\/\/weseek.co.jp\/?utm_source=connpass-top&amp;utm_medium=web-site&amp;utm_campaign=connpass-top-weseek\">\u682a\u5f0f\u4f1a\u793eWESEEK<\/a>\u306f\u3001\u30b7\u30b9\u30c6\u30e0\u958b\u767a\u306e\u30d7\u30ed\u30d5\u30a7\u30c3\u30b7\u30e7\u30ca\u30eb\u96c6\u56e3\u3067\u3059\u3002<\/p>\n<p>\u3010\u73fe\u5728\u306e\u4e3b\u306a\u4e8b\u696d\u3011<\/p>\n<ol>\n<li>\u901a\u4fe1\u5927\u624b\u4f01\u696d\u306e\u696d\u52d9\u30d5\u30ed\u30fc\u81ea\u52d5\u5316\u30d7\u30ed\u30b8\u30a7\u30af\u30c8<\/li>\n<li>\u30bd\u30fc\u30b7\u30e3\u30eb\u30b2\u30fc\u30e0\u306e\u53d7\u8a17\u958b\u767a<\/li>\n<li>\u81ea\u793e\u767a\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9\u30d7\u30ed\u30c0\u30af\u30c8\u300c<a href=\"https:\/\/growi.org\/ja\/?utm_source=connpass-top&amp;utm_medium=web-site&amp;utm_campaign=connpass-top-growi\"><strong>GROWI<\/strong><\/a>\u300d\u300c<strong><a href=\"https:\/\/growi.cloud\/?utm_source=connpass-top&amp;utm_medium=web-site&amp;utm_campaign=connpass-top-growi-cloud\">GROWI.cloud<\/a><\/strong>\u300d\u306e\u958b\u767a<\/li>\n<\/ol>\n<h3>GROWI<\/h3>\n<p><a href=\"https:\/\/growi.org\/ja\/?utm_source=connpass-top&amp;utm_medium=web-site&amp;utm_campaign=connpass-top-growi\"><strong>GROWI<\/strong><\/a>\u306f\u3001Markdown\u8a18\u6cd5\u3067\u30da\u30fc\u30b8\u3092\u8a18\u8ff0\u3067\u304d\u308b\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9\u306eWiki\u30b7\u30b9\u30c6\u30e0\u3067\u3059\u3002<\/p>\n<h3>GROWI.cloud<\/h3>\n<p><a href=\"https:\/\/growi.cloud\/?utm_source=connpass-top&amp;utm_medium=web-site&amp;utm_campaign=connpass-top-growi-cloud\"><strong>GROWI.cloud<\/strong><\/a>\u306fOSS\u306eGROWI\u3092\u5c02\u9580\u7684\u77e5\u8b58\u304c\u306a\u304f\u3066\u3082\u7c21\u5358\u306b\u904b\u7528\u30fb\u7ba1\u7406\u3067\u304d\u308b\u3001\u6cd5\u4eba\u30fb\u500b\u4eba\u5411\u3051\u306e\u5546\u7528\u30b5\u30fc\u30d3\u30b9\u3067\u3059\u3002<\/p>\n<p>\u5927\u624bSIer\u30fbISP\u3084\u4e2d\u5c0f\u4f01\u696d\u3001\u5927\u5b66\u306e\u7814\u7a76\u5ba4\u306a\u3069\u69d8\u3005\u306a\u5834\u6240\u3067\u3054\u5229\u7528\u3044\u305f\u3060\u3044\u3066\u304a\u308a\u307e\u3059\u3002<\/p>\n<p>\u3010\u4e3b\u306a\u7279\u5fb4\u3011<\/p>\n<ul>\n<li>\u30c6\u30ad\u30b9\u30c8\u3082\u56f3\u8868\u3082\u3069\u3093\u3069\u3093\u66f8\u3051\u308b\u3001\u5f37\u529b\u306a\u7de8\u96c6\u6a5f\u80fd<\/li>\n<li>\u30c1\u30fc\u30e0\u62e1\u5927\u306b\u8fc5\u901f\u306b\u5bfe\u5fdc\u3067\u304d\u308b\u7ba1\u7406\u8005\u5411\u3051\u6a5f\u80fd\u3092\u63d0\u4f9b<\/li>\n<li>\u5145\u5b9f\u3057\u305f\u6a5f\u80fd\u30fb\u30b5\u30dd\u30fc\u30c8\u3067\u30a8\u30f3\u30bf\u30fc\u30d7\u30e9\u30a4\u30ba\u306b\u3082\u5bfe\u5fdc<\/li>\n<\/ul>\n<p>\u3010\u5c0e\u5165\u4e8b\u4f8b\u8a18\u4e8b\u3011<\/p>\n<p><a href=\"https:\/\/growi.cloud\/interviews\/mfeed\/?utm_source=connpass-top&amp;utm_medium=web-site&amp;utm_campaign=mf:embed:cite\">\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u30de\u30eb\u30c1\u30d5\u30a3\u30fc\u30c9\u682a\u5f0f\u4f1a\u793e\u69d8<\/a><\/p>\n<p><a href=\"https:\/\/growi.cloud\/interviews\/hikky:embed:cite\">\u682a\u5f0f\u4f1a\u793eHIKKY\uff08VR\u6cd5\u4ebaHIKKY\uff09\u69d8<\/a><\/p>\n<h3>WESEEK Tech Conference<\/h3>\n<p>WESEEK Tech Conference\u306f\u3001\u682a\u5f0f\u4f1a\u793eWESEEK\u304c\u4e3b\u50ac\u3059\u308b\u30a8\u30f3\u30b8\u30cb\u30a2\u5411\u3051\u306e\u52c9\u5f37\u4f1a\u3067\u3059\u3002<br \/>\u6708\u306b2\u56de\u307b\u3069\u3001WESEEK\u306b\u6240\u5c5e\u3059\u308b\u30a8\u30f3\u30b8\u30cb\u30a2\u304c\u69d8\u3005\u306a\u30c6\u30fc\u30de\u3067\u767a\u8868\u3092\u884c\u3046\u4e88\u5b9a\u3067\u3059\u3002<\/p>\n<p>\u6b21\u56de\u306f\u30019\/16(\u6728) 19:00~20:00\u300e\u65e2\u5b58Rails\u30a2\u30d7\u30ea\u3092SSO\u5316\u3057\u3066\u3001\u672c\u756a\u74b0\u5883\u3067\u6d3b\u7528\u3057\u305f\u8a71\u300f<\/p>\n<p>\u65e2\u5b58\u306e Rails \u30a2\u30d7\u30ea\u3092 OpenID Connect \u306b\u5bfe\u5fdc\u3055\u305b\u3001\u5f0a\u793e\u3068\u53d6\u5f15\u304c\u3042\u308b\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u30de\u30eb\u30c1\u30d5\u30a3\u30fc\u30c9\u69d8\u306e\u30dd\u30fc\u30bf\u30eb\u30b5\u30a4\u30c8\u306b\u5c0e\u5165\u3059\u308b\u307e\u3067\u306e\u7d4c\u7def\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<br \/>\n\u307e\u305f\u3001OpenID Connect \u57fa\u76e4\u3092\u6d3b\u7528\u3057\u305f\u8907\u6570\u306e\u30d0\u30c3\u30af\u30a8\u30f3\u30c9\u3084\u30b5\u30a4\u30c8\u3067\u8a8d\u8a3c\u3001\u8a8d\u53ef\u3092\u7d71\u4e00\u3057\u305f\u4e8b\u4f8b\u3082\u3042\u308f\u305b\u3066\u304a\u8a71\u3057\u3057\u307e\u3059\u3002<\/p>\n<p>\u73fe\u5728\u3001connpass\u3084TECH PLAY\u3067\u53c2\u52a0\u53d7\u4ed8\u4e2d\u3067\u3059\u3002\u7686\u69d8\u306e\u3054\u53c2\u52a0\u3092\u304a\u5f85\u3061\u3057\u3066\u304a\u308a\u307e\u3059\uff01<br \/>\n<a href=\"https:\/\/weseek.connpass.com\/event\/223217\/\">https:\/\/weseek.connpass.com\/event\/223217\/<\/a><\/p>\n<p><a href=\"https:\/\/techplay.jp\/event\/829274\">TECH PLAY\u306f\u3053\u3061\u3089\u304b\u3089<\/a><\/p>\n<h3>\u4e00\u7dd2\u306b\u50cd\u304f\u4ef2\u9593\u3092\u52df\u96c6\u3057\u3066\u3044\u307e\u3059<\/h3>\n<p>\u6771\u4eac\u306e\u9ad8\u7530\u99ac\u5834\u30aa\u30d5\u30a3\u30b9\u3001\u5927\u5206\u306b\u3042\u308b\u5225\u5e9c\u30b5\u30c6\u30e9\u30a4\u30c8\u30aa\u30d5\u30a3\u30b9\u306b\u3066\u30a8\u30f3\u30b8\u30cb\u30a2\u3092\u52df\u96c6\u3057\u3066\u304a\u308a\u307e\u3059\u3002<\/p>\n<p>\u4e2d\u9014\u63a1\u7528\u3060\u3051\u3067\u306f\u306a\u304f\u3001\u30a4\u30f3\u30bf\u30fc\u30f3\u30b7\u30c3\u30d7\u3082\u7a4d\u6975\u7684\u306b\u53d7\u3051\u5165\u308c\u3066\u3044\u307e\u3059\uff01<\/p>\n<p>\u8a73\u3057\u3044\u52df\u96c6\u8981\u9805\u306f\u3001\u5f0a\u793eHP\u306e<a href=\"https:\/\/weseek.co.jp\/recruit.html\">\u63a1\u7528\u30da\u30fc\u30b8<\/a>\u304b\u3089\u3054\u78ba\u8a8d\u304f\u3060\u3055\u3044\u3002<\/p>\n<h4>\u95a2\u9023\u8a18\u4e8b<\/h4>\n<p><a href=\"https:\/\/ja.reactjs.org\/docs\/uncontrolled-components.html\">React Uncontrolled<\/a><\/p>\n<p><a href=\"https:\/\/react-hook-form.com\/\">React Hook Form<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u3053\u306e\u8a18\u4e8b\u306f\u30012021\/9\/2 \u306b\u884c\u308f\u308c\u305f WESEEK Tech Conference \u306e\u5185\u5bb9\u3092\u307e\u3068\u3081\u305f\u3082\u306e\u3067\u3059\u3002<\/p>\n","protected":false},"author":8,"featured_media":1246,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[31,51,2],"tags":[],"_links":{"self":[{"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/posts\/1238"}],"collection":[{"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/comments?post=1238"}],"version-history":[{"count":10,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/posts\/1238\/revisions"}],"predecessor-version":[{"id":4039,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/posts\/1238\/revisions\/4039"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/media\/1246"}],"wp:attachment":[{"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/media?parent=1238"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/categories?post=1238"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/tags?post=1238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}