エイチームライフスタイル アドベントカレンダー2019、18日目は株式会社エイチームライフスタイル、フロントエンドデザイナ@seiraが担当します。
最近はReact, Rail, Sass, php, jQuery などを触っています。
まずはReact-Hook-Formを知る
github: https://github.com/react-hook-form/react-hook-form
公式サイト: https://react-hook-form.com/
(日本語訳も用意されてる! UI/UXもイケてるサイトです)
↓↓公式サイトのスクショ↓↓
hook は React16.8 で追加された新機能で、classを書かずにstateが扱えるようになりました。
必見!!Examples
公式サイト内APIでも利用したいメソットごとにサンプルが用意されています。
GitHub README にあるExamplesもオススメ。
こんなことやりたい!が見つかるし、 色々触って動作確認出来ます。
さっそくReact-Hook-FormをInstall
$ yarn add react-hook-form
作ってみたフォーム
入力画面コンポーネント Contact.js と入力内容確認画面コンポーネント Confirm.js を作成。
入力内容確認画面は、submitボタンを押した時に表示され、表示箇所までにゅるっと移動する仕組み。
こんなフォーム | バリデートっ | 入力内容確認画面 |
---|---|---|
|
コード解説
入力画面コンポーネント Contact.js
公式サイトでuseFormのメソッドが詳しく解説されています。
import React, {useState} from 'react'
//stateを持った値と、それを更新するための関数を返したい
import {Element, scroller} from 'react-scroll'
//任意のターゲットに移動させたい
import useForm from 'react-hook-form'
//React-Hook-Formをimport
import Confirmation from './Confirmation'
//入力内容確認画面を表示させるcomponent
import './index.css'
//今回スタイリングは別ファイルで
const Contact = () => {
const {register, handleSubmit, watch, reset, errors, getValues} = useForm()
//useFormを呼び出して使いたいメソッドを書く
const [isConfirmationVisible, setIsConfirmationVisible] = useState(false)
//isConfirmationVisibleにstateを持たせて、入力内容確認画面の表示・非表示をコントロール
//isConfirmationVisibleの初期値はfalseで入力内容確認画面は非表示に
const hideConfirmation = () => setIsConfirmationVisible(false)
//入力内容確認画面の閉じるボタンを押した時非表示にする関数を宣言
const onSubmitData = () => setIsConfirmationVisible(true)
//submitボタンを押した時、入力内容確認画面を表示させる
const scrollToTarget = () => {
//にゅるっと移動させる関数を宣言
scroller.scrollTo('scrollTarget', {
duration: 800,
delay: 0,
smooth: 'easeOutQuint'
})
}
const Department = watch('department')
const Name = watch('name')
const Email = watch('email')
const Contact = watch('contact')
//watchに各フォーム部品のnameの値を引数で渡すとでタイムリーで入力状態を監視してる
return(
<>
<h2>Contact</h2>
<form onSubmit={handleSubmit(onSubmitData)} className='contactBox'>
{/*onSubmit(入力フォームの送信ボタンがクリックされた時に発生するイベント)で入力された値をhandleSubmitで取り出す*/}
<label htmlFor='department'>所属部署
<span className={`requiredIcon ${Department ? 'is-ok' : 'is-required'}`}>
{Department ? 'OK' :'必須'}
</span>
</label>
<select name='department' ref={register({ required: true })}>{/*入力必須項目*/}
<option value='' hidden>所属部署を選択</option>
<option value='クリエイティブ戦略部'>クリエイティブ戦略部</option>
<option value='名古屋開発部'>名古屋開発部</option>
<option value='営業部'>営業部</option>
<option value='マーケティング部'>マーケティング部</option>
</select>
{errors.department && <p className='formError'>所属部署を選択してください</p>}{/*validationが通らなければerrorがtrueになる*/}
<label htmlFor='name'>氏名
<span className={`requiredIcon ${Name ? 'is-ok' : 'is-required'}`}>{/*nameが入力されてたらtrue*/}
{Name ? 'OK' :'必須'}
</span>
</label>
<input
name='name'
placeholder='氏名を入力'
ref={register({required: true})} />
{errors.name && <p className='formError'>名字を入力して下さい</p>}{/*nameが正しく入力されていない時に表示される*/}
<label htmlFor='email'>メールアドレス
<span className={`requiredIcon ${Email && !errors.email ? 'is-ok': 'is-required'}`}>
{Email && !errors.email ? 'OK' :'必須' }
</span>
</label>
<input
type='email'
name='email'
placeholder='メールアドレスを入力'
ref={register({
required: true,
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i
})}
/>
{errors.email && <p className='formError'>メールアドレスを正しく入力して下さい</p>}
<label htmlFor='contact'>問い合わせ内容
<span className={`requiredIcon ${Contact && !errors.contact ? 'is-ok': 'is-required'}`}>
{Contact && !errors.contact ? 'OK' :'必須' }
</span>
</label>
<textarea
name='contact'
placeholder='問い合わせ内容を入力'
ref={register({
required: true,
rows: 8,
minLength: 1,
maxLength: 300
})}
/>
{errors.contact && <p className='formError'>問い合わせ内容を300文字以内で入力して下さい</p>}
<div className='btnBox'>
<input
type='button'
onClick={reset}//入力内容もstateもクリア
value='クリア'
className='button'/>
<input
type='submit'
value='入力内容を確認'
onClick={scrollToTarget}//移動先ターゲットにした<Element name='scrollTarget'/>までにゅる移動
className='button'/>
</div>
</form>
<Element name='scrollTarget'/>
{isConfirmationVisible &&//trueの時だけ入力内容確認画面を表示
<Confirmation//入力内容確認画面コンポーネント
values={getValues()}//getValues()でフォーム全体のデータを返してくれる!!
hideConfirmation={hideConfirmation}//入力内容確認画面表示・非表示のstateをConfirmationに渡す
/>
}
</>
)
}
export default Contact
入力内容確認画面コンポーネント Confirm.js
import React from 'react'
import './index.css'
const Confirmation = props => {
const {values, hideConfirmation} = props
//propsで渡ってきたvaluesを受けとって入力内容確認画面で表示
return(
<>
<h2>確認画面</h2>
<div className='contactBox'>
<p>所属部署:{values.department}</p>
<p>氏名:{values.name}</p>
<p>社員番号:{values.registrationNumber}</p>
<p>メールアドレス:{values.email}</p>
<p>携帯電話番号:{values.tel}</p>
<p>問い合わせ内容:{values.contact}</p>
<div className='btnBox'>
<input
type='button'
onClick={hideConfirmation}
//クリックでstateをクリアし、入力内容確認画面コンポーネントを非表示にする
value='閉じる'
className='button'/>
</div>
</div>
</>
)
}
export default Confirmation
stateをfunctionalComponentで扱えるようになって、コードが随分シンプルに。
とにかく触ってみたら、なんとなく分かってきた
公式サイトを読み込んで理解を深めたら、もっとシンプルなコードで同じことが出来そう。
何より注目なのは、実装方法がシンプルなだけでなくReduxFormやFormikに比べてレンダリングやマウントにかかる時間が大幅に削減されていることです。
ReduxFormやFormikからReact-Hook-Form載せ替えメリット大ですね!!
React-Hook-Form 業務でも使ってみたいです。
最後に
Ateam Lifestyle Advent Calendar 2019 の 19日目は、@mziyutが投稿します。
"挑戦"を大事にするエイチームグループでは、一緒に働けるチャレンジ精神旺盛な仲間を募集しています。興味を持たれた方はぜひエイチームグループ採用サイトをごらんください。
参考
github: https://github.com/react-hook-form/react-hook-form
公式サイト: https://react-hook-form.com/jp/