フォームはシンプルで宣言的でなければなりません



多くの人が、ReactJSでフォームを操作するために特定のライブラリを選択することに気付きました。 自分に合ったものを選択したとき、さまざまなライブラリが完璧に見えましたが、設定のフォーム、onSubmitイベントのコールバック、または非同期送信です。 なぜ反応フォーム反応の原則と一致ないのは 、なぜ特別なもののように見えるのですか? これらの質問が発生した場合、またはフォームが気に入った場合は、この記事を読むことをお勧めします。

フォームがどうあるべきか想像してみましょう。


反応のフォームは次のようにする必要があります。


反応のフォームは次のことはできません。


次に、これらのルールに基づいて理想的なフォームを説明してみましょう。

<Form action="/" method="post"> <Validation> <Field type="text" name="firstName"> <Field type="text" name="lastName"> <Transform> <Field type="number" name="minSalary"> <Field type="number" name="maxSalary"> <Transform> <Field type="email" name="email"> </Validation> <button type="submit">Send<button> </Form> 

入力と不明なValidation and Transformの代わりにFieldを除いて、通常のhtmlフォームのように見えます。 Validationタグがフィールドの値をチェックし、それらのエラーメッセージを作成する必要があることを既に推測しているでしょう。 次に、minSalaryフィールドとmaxSalaryフィールドを評価するには、 Transformタグが必要です。

Reactについて何か言いましたか?


反応の現実に早送りし、同じ形式を説明します。

 class MySexyForm extends React.Component { constructor(props) { super(props); this.state = { model: {} }; this.validator = (model, meta) => { let errors = { ...meta.submitErrors }; if(model.firstName && model.firstName.length > 2) { errors = { firstName: ["First name length must be at minimum 2"] }; } if(model.lastName && model.lastName.length > 2) { errors = { ...errors, lastName: ["Last name length must be at minimum 2"] }; } return errors; }; this.transformer = (field, value, model) => { switch (field) { case "minSalary": if (parseInt(value) > parseInt(model.maxSalary)) { return { maxSalary: value }; } case "maxSalary": if (parseInt(value) < parseInt(model.minSalary)) { return { minSalary: value }; } } return {}; }; } onSubmit = (event) => (model) => { event.preventDefault(); console.log("Form submitting:", model); this.props.sendSexyForm(model); //  action           submitErrors  } onModelChange = (model) => { console.log("Model was updated: ", model); this.setState({ model }); } render() { return ( <Form action="/" method="post" onSubmit={this.onSubmit} onModelChange={this.onModelChange} values={this.state.model} initValues={this.props.initValues} > <Validation validator={this.validator} submitErrors={this.props.submitErrors}> <Field type="text" name="firstName"> <Field type="text" name="lastName"> <Transform transformer={this.transformer}> <Field type="number" name="minSalary"> <Field type="number" name="maxSalary"> <Transform> <Field type="email" name="email"> </Validation> <button type="submit">Send<button> </Form> ); } }; 

Fieldコンポーネントの詳細については検討しません。Fieldに渡されたpropと追加の値およびonChangeで入力をレンダリングすることを想像してください。 このフィールドのエラーメッセージも同様です。
新しいフィールドinitValues、values、onModelChange、onSubmit、validator、transformerの外観を説明する価値があります。

Formに追加された小道具から始めましょう。

onSubmitイベントハンドラーを使用すると、フォームsubmitのイベントをインターセプトして、モデル引数を介してこのイベントとフォームフィールドの現在の値にアクセスできます。

onModelChangeイベントハンドラを使用すると、フォームフィールドの変更を追跡できます
を使用して、フィールドの値を制御できます。initValuesを使用すると、初期値を設定できます

この基本的な機能は、反応してフォームを操作するためのほとんどのライブラリを提供します。

Validationタグを検討してください。2つの支柱があります

  1. バリデーター-渡されたフォームフィールドの値に基づいて検証エラーを返す関数
  2. submitErrors-2番目の引数によってバリデーター関数に渡される追加の残りのフィールド。ここでは、送信後にサーバーから受信したエラーを渡します。 基本的に、Validatorを除いて、Validationに渡されるすべての引数はrestに渡されます。

残念ながら、検証の類似または類似の実装を見たことはありませんが、明らかなようです:データを受け取り、それに基づいてエラーを返す検証関数があり、ロジックの副作用はありません。すべてが反応にあるはずです。

変換コンポーネントに移りましょう。 ネストされたフィールドの変更をインターセプトし、関数-トランスフォーマーを呼び出します。トランスフォーマーは3つの引数を取ります。


フォームの他のフィールドを更新するために使用されるフォーム{[field]:value}のオブジェクトを返す必要があります。

また、計算フィールドの明らかな実装。

そして...最後に何がありますか?


最初に宣言的なアプローチと構成を使用したため、検証と変換のコンポーネントを組み合わせて、フィールドの個々のグループに使用できます。

追加の機能(変換と検証)を担当するFormコンポーネントには、追加の小道具はありません。

フィールドは、 コンテキストによってその意味、エラー情報、およびコールバック関数を取得します。これにより、フォームを操作し、責任を委任するための追加のコンポーネントを作成できます。 フォーム自体の外観はhtmlプロジェクションに似ており、理解が容易になります。

反応する痛みのない


私は独自のライブラリを作成しました。これは、フォームをシンプルかつ明確にするのに役立ちます。 コードはGithubで入手できます。

また、記事の実際のをご覧ください。

ご清聴ありがとうございました。


最後まで読んだら、フォームが非常に好きになります。または、記事が面白かったので、コメントを読んで、リアクションのフォームについての意見を聞いてうれしいです。

Source: https://habr.com/ru/post/J354562/


All Articles