Reduxフォームに対応したフォーム状態の管理

提供:Dev Guides
移動先:案内検索

序章

redux-form は、Reduxを利用したフォームを管理するための優れた方法です。 これは、 react-redux を使用してReactのHTMLフォームがすべての状態を保存するためにReduxを使用することを確認するHigher-Order-Component(HOC)です。

redux-formには、アプリケーションの構築に役立つ次のコンポーネントがあります。

  • formReducer():これは、アプリケーションからの変更に基づいてReduxストアを更新する方法を指示する関数です。 これらの変更は、Reduxアクションによって記述されます。 formReducerは、formのRedux状態にマウントする必要があります。
  • reduxForm()reduxForm()関数は高階コンポーネントであり、構成オブジェクトを受け取り、常に新しい関数を返します。 これは、フォームコンポーネントをラップし、ユーザーインタラクションをReduxディスパッチアクションにバインドするために使用されます。
  • <Field/>コンポーネント:ラップされたフォームコンポーネント内に存在するコンポーネント。 フォーム内の入力要素をredux-form logicに接続する方法として機能します。 言い換えれば、それはユーザーが入力したものから入力を取得する方法です。

redux-form APIの詳細については、ドキュメントをご覧ください。

このチュートリアルでは、 redux-form を使用して、検証付きのフォームを作成し、Reduxストアに接続します。

前提条件

このチュートリアルを完了するには、次のものが必要です。

ステップ1-プロジェクトの作成

create-react-appパッケージを使用してReactアプリを構築します。 create-react-appを使用すると、ビルド構成なしでReactアプリを作成できます。 次のターミナルコマンドを実行すると、create-react-appを使用できます。 contact-reduxという名前のフォルダーにReactアプリが自動的に作成されます。

npx create-react-app contact-redux

npxは、5.2以降のバージョンのnpmでのみ機能することに注意してください。 それより前のバージョンを使用していて、コンピューターで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–フォームの作成

Bulma CDNリンクをindex.htmlファイルに追加して、デフォルトのスタイルを追加します。 public/index.htmlファイルを開き、次のコード行をheadタグに追加します。

public / index.html

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">

src/App.jsファイルを編集します。 src/App.jsファイルを開き、ファイルの先頭に以下のコード行を追加します。

src / App.js

import { reduxForm, Field } from 'redux-form';

次に、render()関数に移動し、次のコードで変更します。

src / App.js

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の宣言の直前にこのコードを入力します。

src / App.js

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コンポーネントです。

Fieldコンポーネントはredux-formパッケージに由来し、inputフィールドの記述方法です。 type小道具は、入力のタイプ、つまり、radio入力、checkbox入力、text入力、またはemail入力。 componentプロップは、入力フィールドのタイプを決定します。入力フィールドのタイプは、inputtextareaselectタグ、およびnameです。 propは、以下で作成するreduxストアのフィールドの状態を識別するために使用されるものです。

したがって、redux-formに接続されたフォームを使用するには、ある種のReduxストアをすでに作成しておく必要があります。これを次に行います。

ステップ3–Reduxストアを設定する

作成したフォームコンポーネント(SignInForm)を接続できるReduxストアが必要です。 reduxパッケージをインポートすることから始めましょう。 src/index.jsファイルを開き、基本的にreduxをReactアプリにインポートする次のコード行を追加します。

src / index.js

import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { reducer as formReducer } from 'redux-form';

コードの最初の行は、createStorecombineReducersをインポートします。 createStore は、アプリの完全な状態ツリーを保持するReduxストアを作成するのに役立ち、 combineReducers は、すべてのレデューサー関数を1つのヘルパー関数に管理してから渡すことができます。 createStore。 これらの関数の詳細については、ReduxAPIリファレンスページをご覧ください。

コードの2行目は、react-reduxからProviderをインポートします。 Providerは、ストアの状態をアプリ内のすべてのコンテナーコンポーネントに渡すのに役立ちます。これについては、後で説明します。

コードの3行目は、reducerformReducerとしてインポートします。これを使用して、フォームをReduxストアに接続します。

次に、実際のReduxストアを作成し、Providerコンポーネントを使用して、すべてのコンテナーコンポーネントに適用できることを確認します。 src/index.jsファイルを次のコードブロックで編集します。

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関数を使用して、フォームからReduxストアにformReducerを接続します。 これは基本的に、アクション(この場合はフォームの変更)に応じて状態を更新するために使用されます。 次のコード行は、ReduxのcreateStoreを使用してストアを作成するために使用されます。

この新しく作成されたストアは、AppコンポーネントにラップされたProviderの助けを借りてアプリのすべての部分で利用できるようになり、store

フォームに戻り、最後にストアに接続しましょう。

##ステップ4–フォームをredux-formに接続する

フォームコンポーネントがありますが、まだredux-formに接続されていません。 それを修正しましょう。 class App extends Componentの直前、およびSignInFormプレゼンテーションコンポーネントの宣言の直後に、このコードブロックを入力します。

src / index.js

SignInForm = reduxForm({
  form: 'signIn',
})(SignInForm);

上記のコードブロックでは、SignInFormは、reduxForm高階コンポーネントを使用してredux接続された形式になっています。 これは、フォームがストアに接続されたことを意味します。 注意すべき点の1つは、構成キーformです。これは識別子として使用され、フォームコンポーネントの一意の名前を提供するために使用されます。 それらが複数の形式である場合、それらの異なる状態をより適切に管理するために、別々の名前を使用する必要があります。

次に行う必要があるのは、[送信]ボタンをクリックしたときに何が起こるかを構成することです。 理想的なアプリでは、リモートAPIまたは一部のデータベースにデータを送信する必要がありますが、デモンストレーションの目的で、フォームデータをブラウザーコンソールに記録します。 そのためには、小道具からフォームデータを取得し、それらをどこかに保存する必要があります。

SignInFormコンポーネント内で、returnステートメントのすぐ上にコード行を追加します。

[label src/index.js]  
  const { handleSubmit } = props;
  return <form **onSubmit={handleSubmit}** className="form">

SignInForm形式のpropsは、handleSubmitに分解されます。 handleSubmit関数は、送信ボタンがクリックされたときにonSubmitイベントのハンドラーとしてフォームで使用されます。

最後に、src/App.jsファイルのAppコンポーネント内に、フォームデータをブラウザーコンソールに記録する関数を作成します。 render()関数の直前のファイルに以下のコードブロックを追加します。

src / App.js

  handleSignIn = values => {
        console.log(values);
    };

次に、handleSignIn関数をSignInFormコンポーネントのイベントハンドラーとして追加します。 redux-formは、フォームから取得したデータを自動的に確認します。これは、上記のhandleSubmit関数のおかげで、基本的にSignInFormコンポーネントがコンソールに記録される必要があります。

src / App.js

    <SignInForm onSubmit={this.handleSignIn} />

これで、npm startターミナルコマンドを実行してアプリを起動できます。 フォームに記入し、[送信]をクリックすると、コンソールに記録された値が表示されます。

ステップ5–検証を追加する

フォームの作成に関しては検証が重要であり、redux-formにはいくつかの検証機能が付属しており、これから実装します。 src/App.jsファイルに、以下のコードブロックを入力します。

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;
};

validate関数は、フォームの検証エラーをチェックするために使用されます。 valパラメーターは、さまざまなフィールドの検証をチェックするために使用されます。 最初に、errorsオブジェクトが空であるかどうかを確認します。空のオブジェクトは、明らかにエラーがないことを意味します。 次に、条件付きロジックを使用して、フィールドが空であるかどうかを確認します。空である場合は、対応するエラーをスローします。 上記のコードブロックでは、firstNamelastNameemail、およびageの検証のみを行っています。 email検証条件では、空かどうかを確認し、regexを使用して有効なメールかどうかも確認します。また、age検証条件では、空かどうかを確認します。数とユーザーが18未満の場合。

次に、検証関数をredux-formに登録して、検証テストの実行に使用できるようにします。 validate関数をredux-form高階コンポーネントに追加します。

src / index.js

SignInForm = reduxForm({
  form: 'signIn',
  validate,
})(SignInForm);

検証機能の準備が整い、redux-form HOCに登録されたので、エラーが発生するたびにエラーを表示し、フォームで新しく作成されたコンポーネントを使用する再利用可能なコンポーネントを作成します。

src / index.js

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>
)

renderFieldコンポーネントは、inputオブジェクトの小道具、label、入力のtype、およびredux-formプロパティ。 {touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}の行は、フォームフィールドがクリック/フォーカスされたときにエラーがあるかどうかを示すエラーメッセージが表示されることを意味します。 また、エラーが発生した場合、フォームは送信されません。

ここで、フォームをチェックして無効な入力を入力しようとしたり、検証テストのあるフィールドをスキップしたりすると、フォームの下にエラーメッセージが表示されます。

結論

このチュートリアルでは、redux-formを使用してフォームを作成し、Reduxストアに接続しました。 外部スキーマ検証ツールを必要とせずに、フォームに同期検証を追加しました。

redux-form の詳細については、公式サイトをご覧ください。また、の例を参照してさらに詳しく調べることができます。

このチュートリアルの完成したコードは、GitHubにあります。