Reduxフォームに対応したフォーム状態の管理
序章
redux-form は、Reduxを利用したフォームを管理するための優れた方法です。 これは、 react-redux を使用してReactのHTMLフォームがすべての状態を保存するためにReduxを使用することを確認するHigher-Order-Component(HOC)です。
redux-formには、アプリケーションの構築に役立つ次のコンポーネントがあります。
-
formReducer()
:これは、アプリケーションからの変更に基づいてReduxストアを更新する方法を指示する関数です。 これらの変更は、Reduxアクションによって記述されます。formReducer
でRedux状態にマウントする必要がありますform
. -
reduxForm()
:reduxForm()
関数は高階コンポーネントであり、構成オブジェクトを受け取り、常に新しい関数を返します。 これは、フォームコンポーネントをラップし、ユーザーインタラクションをReduxディスパッチアクションにバインドするために使用されます。 -
The
<Field/>
コンポーネント:ラップされたフォームコンポーネント内に存在するコンポーネント。 これは、フォーム内の入力要素をに接続する方法として機能します。redux-form logic
. 言い換えれば、それはユーザーが入力したものから入力を取得する方法です。
あなたはについてもっと読むことができます redux-form
ドキュメントのAPI。
このチュートリアルでは、 redux-form を使用して、検証付きのフォームを作成し、Reduxストアに接続します。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- Node.jsのローカル開発環境。 Node.jsをインストールしてローカル開発環境を作成する方法に従ってください
ステップ1-プロジェクトの作成
create-react-appパッケージを使用してReactアプリを構築します。 create-react-app
ビルド構成なしでReactアプリを作成できます。 使用できます create-react-app
次のターミナルコマンドを実行します。 それは自動的にあなたのためのReactアプリをというタイトルのフォルダに作成します contact-redux
.
- npx create-react-app contact-redux
注意することが重要です npx
のバージョンでのみ動作します npm
5.2以上です。 それより前のバージョンをお持ちで、それでも使用したい場合 create-react-app
お使いのコンピュータで。 以下のターミナルコマンドを実行してインストールします create-react-app
Reactアプリを起動します。
- npm install -g create-react-app
- create-react-app contact-redux
ディレクトリに移動し、開発サーバーを起動して、すべてが機能することを確認します。 次のコマンドを実行して、新しく作成されたReactアプリを開発モードで起動します。
- npm start
ブラウザに次のように表示されます。
これで、Reactアプリが稼働しています。
次のコマンドを実行して、フォームに必要な依存関係を追加します。
- npm install --save redux react-redux redux-form
- redux -状態コンテナであり、redux-formが機能するための前提条件です。
- react-redux -React ReduxはReduxの公式Reactバインディングであり、redux-formが機能するための前提条件でもあります
- redux-form-このチュートリアルで使用されているパッケージ。
インストールが完了すると、お問い合わせフォームで作業できます。
ステップ2–フォームの作成
BulmaCDNリンクをに追加します index.html
いくつかのデフォルトのスタイルを追加するためにファイル。 を開きます public/index.html
ファイルを作成し、次のコード行を head
鬼ごっこ:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">
にいくつかの編集を行います src/App.js
今すぐファイルします。 開く src/App.js
ファイルを作成し、ファイルの先頭に以下のコード行を追加します。
import { reduxForm, Field } from 'redux-form';
次に、 render()
関数を作成し、次のコードで変更します。
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React x redux-form</h1>
</header>
<div className="container">
<p className="App-intro">
Contact Form
</p>
<SignInForm />
</div>
</div>
);
}
紹介文が変更され、最も重要なのは、 <SignInForm />
以下で作成するコンポーネント。 必要なフォームを返すシンプルなコンポーネントになり、に接続されます redux-form
成分。 同じように src/App.js
ファイルの場合、宣言の直前にこのコードを入力します class App extends Component
.
let SignInForm = props => {
return <form className="form">
<div className="field">
<div className="control">
<label className="label">First Name</label>
<Field className="input" name="firstName" component="input" type="text" placeholder="First Name"/>
</div>
</div>
<div className="field">
<div className="control">
<label className="label">Last Name</label>
<Field className="input" name="lastName" component="input" type="text" placeholder="Last Name"/>
</div>
</div>
<div className="field">
<div className="control">
<label className="label">Email</label>
<Field className="input" name="email" component="input" type="email" placeholder="Email Address"/>
</div>
</div>
<div className="field">
<div className="control">
<label className="label">Proficiency</label>
<div className="select">
<Field className="input" name="proficiency" component="select">
<option />
<option value="beginner">Beginner Dev</option>
<option value="intermediate">Intermediate Dev</option>
<option value="expert">Expert Dev</option>
</Field>
</div>
</div>
</div>
<div className="field">
<div className="control">
<label className="label">Age</label>
<Field className="input" name="age" component="input" type="number" placeholder="Age"/>
</div>
</div>
<div className="field">
<div className="control">
<label className="checkbox">
<Field name="saveDetails" id="saveDetails" component="input" type="checkbox"/>
Save Details
</label>
</div>
</div>
<div className="field">
<div className="control">
<label className="label">Message</label>
<Field className="textarea" name="message" component="textarea" />
</div>
</div>
<div className="field">
<div className="control">
<button className="button is-link">Submit</button>
</div>
</div>
</form>;
};
このコードでは、名、姓、年齢などの情報をユーザーに尋ねる最小限の連絡フォームを設定します。 この形式の興味深いビットは Field
成分。
The Field
コンポーネントはから来ます redux-form
パッケージとそれは私たちが書く方法です input
分野。 The type
propは、入力のタイプを示します。つまり、 radio
入力、 checkbox
入力、 text
入力または email
入力。 The component
propは、入力フィールドのタイプを決定します。 input
, textarea
また select
タグと name
propは、以下で作成するreduxストアのフィールドの状態を識別するために使用されるものです。
したがって、redux-formに接続されたフォームを使用するには、ある種のReduxストアをすでに作成しておく必要があります。これを次に行います。
ステップ3–Reduxストアを設定する
フォームコンポーネントを接続できるReduxストアが必要です(SignInForm
)作成しました。 インポートすることから始めましょう redux
パッケージ。 を開きます src/index.js
ファイルを作成し、基本的にインポートしている次のコード行を追加します redux
Reactアプリに。
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { reducer as formReducer } from 'redux-form';
コードの最初の行はインポートします createStore
と combineReducers
. createStore は、アプリの完全な状態ツリーを保持するReduxストアを作成するのに役立ち、 combineReducers は、すべてのレデューサー関数を1つのヘルパー関数に管理してから渡すことができます。 createStore
. これらの関数の詳細については、ReduxAPIリファレンスページをご覧ください。
コードの2行目はインポートします Provider
から react-redux
. Provider
ストアの状態をアプリ内のすべてのコンテナーコンポーネントに渡すのに役立ちます。これがどのように機能するかについては後で説明します。
コードの3行目はインポートします reducer
なので formReducer
これを使用して、フォームをReduxストアに接続します。
次に、実際のReduxストアを作成し、を使用してすべてのコンテナコンポーネントに適用できることを確認します。 Provider
成分。 編集します src/index.js
次のコードブロックを持つファイル。
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { reducer as formReducer } from 'redux-form';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
const rootReducer = combineReducers({
form: formReducer,
});
const store = createStore(rootReducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
registerServiceWorker();
上記のコードブロックでは、 combineReducers
接続する機能 formReducer
フォームからReduxストアまで。 これは基本的に、アクション(この場合はフォームの変更)に応じて状態を更新するために使用されます。 次のコード行は、を使用してストアを作成するために使用されます createStore
Reduxから。
この新しく作成されたストアは、アプリのすべての部分で利用できるようになります。 Provider
包まれている App
コンポーネントとそれはまたである店の小道具を受け入れます store
それは上で作成されました。
フォームに戻り、最後にストアに接続しましょう。
##ステップ4–フォームをredux-formに接続する
フォームコンポーネントがありますが、に接続されていません redux-form
まだ。 それを修正しましょう。 このコードブロックを、 class App extends Component
SignInFormプレゼンテーションコンポーネントの宣言の直後。
SignInForm = reduxForm({
form: 'signIn',
})(SignInForm);
上記のコードブロックでは、 SignInForm
を使用してredux接続形式になります reduxForm
高階コンポーネント。 これは、フォームがストアに接続されたことを意味します。 注意すべきことの1つは、構成キーです form
、識別子として使用され、フォームコンポーネントに一意の名前を提供するために使用されます。 それらが複数の形式である場合、それらの異なる状態をより適切に管理するために、別々の名前を使用する必要があります。
次に行う必要があるのは、[送信]ボタンをクリックしたときに何が起こるかを構成することです。 理想的なアプリでは、リモートAPIまたは一部のデータベースにデータを送信する必要がありますが、デモンストレーションの目的で、フォームデータをブラウザーコンソールに記録します。 そのためには、小道具からフォームデータを取得し、それらをどこかに保存する必要があります。
内部 SignInForm
コンポーネントのすぐ上にコード行を追加します return
声明。
[label src/index.js]
const { handleSubmit } = props;
return <form **onSubmit={handleSubmit}** className="form">
The props
の中に SignInForm
フォームはに分解されます handleSubmit
. The handleSubmit
関数は、フォームでハンドラーとして使用されます。 onSubmit
送信ボタンがクリックされたときのイベント。
最後に、 App
のコンポーネント src/App.js
ファイルの場合、フォームデータをブラウザコンソールに記録する関数を作成します。 以下のコードブロックをファイルの直前のファイルに追加します render()
関数。
handleSignIn = values => {
console.log(values);
};
次に、 handleSignIn
のイベントハンドラとして機能します SignInForm
成分。 redux-form
フォームから取得したデータを自動的に確認します。これは基本的に SignInForm
コンポーネントは、おかげでコンソールに記録する必要があります handleSubmit
上記の機能。
<SignInForm onSubmit={this.handleSignIn} />
これで、を実行してアプリを起動できます npm start
ターミナルコマンド。 フォームに記入し、[送信]をクリックすると、コンソールに記録された値が表示されます。
ステップ5–検証を追加する
フォームの作成と redux-form
いくつかの検証機能が付属しており、これを実装します。 の中に src/App.js
ファイルに、以下のコードブロックを入力します。
const validate = val => {
const errors = {};
if (!val.firstName) {
console.log('First Name is required');
errors.firstName = 'Required';
}
if (!val.lastName) {
console.log('Last Name is required');
errors.lastName = 'Required';
}
if (!val.email) {
console.log('email is required');
errors.email = 'Required';
} else if (!/^.+@.+$/i.test(val.email)) {
console.log('email is invalid');
errors.email = 'Invalid email address';
}
if (!val.age) {
errors.age = 'Required'
} else if (isNaN(Number(val.age))) {
errors.age = 'Must be a number'
} else if (Number(val.age) < 18) {
errors.age = 'Sorry, you must be at least 18 years old'
}
return errors;
};
The validate
関数は、フォームの検証エラーをチェックするために使用されます。 The val
パラメータは、さまざまなフィールドの検証をチェックするために使用されます。 まず、 errors
オブジェクトが空です。空のオブジェクトは明らかにエラーがないことを意味します。 次に、条件付きロジックを使用して、フィールドが空であるかどうかを確認します。空である場合は、対応するエラーをスローします。 上記のコードブロックでは、次の検証のみを行っています firstName
, lastName
, email
、 と age
. の中に email
検証条件付きで、それが空であるかどうかをチェックし、それが有効な電子メールであるかどうかもチェックします。 regex
とで age
検証条件付きで、それが空であるかどうか、数値であるかどうか、およびユーザーが18未満であるかどうかを確認します。
次に、検証関数をに登録します redux-form
検証テストの実行に使用を開始できるようにします。 追加します validate
機能する redux-form
高階コンポーネント:
SignInForm = reduxForm({
form: 'signIn',
validate,
})(SignInForm);
これで、検証関数の準備が整い、に登録されました。 redux-form
HOC、エラーが発生するたびにエラーを表示する再利用可能なコンポーネントを構築し、フォームで新しく作成されたコンポーネントを使用します。
const renderField = ({ input, label, type, meta: { touched, error, warning } }) => (
<div>
<div className="control">
<label className="field">{label}</label>
<input className="input" {...input} placeholder={label} type={type}/>
{touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
</div>
</div>
)
The renderField
コンポーネントは、の小道具を取り入れます input
オブジェクト、 label
、 type
入力と meta
これは redux-form
財産。 この線 {touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
フォームフィールドがクリック/フォーカスされたときにエラーがあるかどうかを示すエラーメッセージが表示されることを意味します。 また、エラーが発生した場合、フォームは送信されません。
ここで、フォームをチェックして無効な入力を入力しようとしたり、検証テストのあるフィールドをスキップしたりすると、フォームの下にエラーメッセージが表示されます。
結論
このチュートリアルでは、でフォームを作成しました redux-form
そしてそれをReduxストアに接続しました。 外部スキーマ検証ツールを必要とせずに、フォームに同期検証を追加しました。
あなたはについてもっと読むことができます redux-form
公式サイトで、の例を調べてさらに詳しく調べることができます。
このチュートリアルの完成したコードは、GitHubにあります。