ReactJSとここのGeocoder自動補完によるストリートアドレス形式の検証


あなたが顧客があなたから購入したいならば、送料または請求先アドレスを必要とすることはあなたのreactjsアプリケーションの一部になるかもしれません.ほぼすべてのデータベースコースでは、通常のフォームでデータモデルを整理する方法の良いベースラインのチュートリアルとして郵便アドレスを見ていますが、クライアント側ではどうですか?
レコードをガベージアウトしないようにするには、アドレスの妥当性検査を行うためにしばらく時間がかかります.ユーザーエクスペリエンスを改善したい場合はHERE Geocoder Autocomplete API 助けるかもしれません.このRESTサービスでは、入力された各文字の提案を提供することによってスペルミスを避けるのを助けることができるより少ないキーストロークのアドレスを識別できます.また、空間と地域フィルタのようないくつかの強力な機能も同様に関連性を改善するためです.

プロジェクト


このプロジェクトでは、このモックアップによって示されるような簡単なアドレスフォームを作成します.

「2168 sha」と入力すると、残りのアドレスが自動的に入力されます.その後、アドレスをチェックすることができますHERE Geocoder API 確かに我々は緯度と経度値を識別することができます.

始める


単一のページの形式に何の量の29542ファイルを生成するoverkillのように見えるかもしれませんが、私はまだ作成反応アプリを起動することをお勧めします.ブラウザでのライブリロードを持つローカルサーバーのような開発ツールは、迅速な反復に役立ちます.次のように実行しましょう.
create-react-app app
cd app
npm install bootstrap axios
npm start
ご覧の通り、私も使用しますBootstrap CSSフレームワークとしてaxios HTTPクライアントとして.

反応を考える


ReactJSチュートリアルでは、いくつかの基本的な手順に従って反応の概念を以下の通り.
  • コンポーネント階層にUIを割る
  • 静的バージョンのビルド
  • UI状態の最小表現を識別する
  • 国家が生きるべき場所を特定する
  • 逆データフローの追加
  • コンポーネント階層にUIを割る


    以前から私たちのモックアップを使用して、我々は多くのコンポーネントにページを分割することができますように見えます.

    静的バージョンのビルド


    一番下から始まると、addressitemはラベルとフォーム要素からなる単一の行項目です.ES 6クラスを使用して他のコンポーネントで使用するクラスをエクスポートします.
    import React, { Component } from 'react';
    
    class AddressItem extends Component {
      render() {
        return (
            <div className="row form-group justify-content-start">
                <label className="col-sm-4 col-form-label">{this.props.label}</label>
                <div className="col-xl-8">
                  <input
                    type="text"
                    defaultValue={this.props.value}
                    onChange={this.props.onChange}
                    className="form-control"
                    placeholder={this.props.placeholder} />
                </div>
            </div>
          );
      }
    }
    
    export default AddressItem;
    
    
    AddressSegencesおよびAddressInputコンポーネントは、両方とも、それらのRenderメソッドのaddressitemを使用します.
    // app/src/AddressSuggest.js
    class AddressSuggest extends Component {
      render() {
        return (
          <AddressItem label="Address" value={this.props.query} placeholder="start typing" />
          );
      }
    }
    
    あなたは、私が簡潔さのためにここの輸入と輸出をスキップしたと認めるかもしれません、しかし、彼らはまだ必要です.最後にリンクされているGithubリポジトリから完全なリストにそれらを見つけることができます.
    // app/src/AddressInput.js
    class AddressInput extends Component {
      render() {
        return (
          <div className="card"><div className="card-body">
          <AddressItem label="Street" value={this.props.street} placeholder="" readonly="true" />
          <AddressItem label="City" value={this.props.city} placeholder="" readonly="true" />
          <AddressItem label="State" value={this.props.state} placeholder="" readonly="true" />
          <AddressItem label="Postal Code" value={this.props.code} placeholder="" readonly="true" />
          <AddressItem label="Country" value={this.props.country} placeholder="" readonly="true" />
          </div></div>
        );
      }
    }
    
    
    階層を継続すると、AddressFormは入力フォーム全体をSubmitボタンと組み合わせて検証を行います.
    // app/src/AddressForm.js
    class AddressForm extends Component {
      render() {
        return (
            <div className="container">
              <AddressSuggest />
                query="4168 S"
                />
              <AddressInput
                street="4168 Shattuck Ave"
                city="Berkeley"
                state="CA"
                code="94704"
                country="USA"
                />
              <br/>
              <button type="submit" className="btn btn-primary">Check</button>
              <button type="submit" className="btn btn-outline-secondary">Clear</button>
            </div>
          );
      }
    }
    
    
    ご覧のように、任意の静的な値をどのように対話的な振る舞いに対処する必要があるかを見るには、ASプロパティの静的な値をハードコーディングしました.次に、これらのプロパティの一部を状態に置き換える必要があります.

    追跡状態


    ここまでは、変更不可能なプロパティを使用しています.今、我々は戻って、状態を追跡し始めます.追跡する最小限の情報
  • 時間をかけて変更するユーザーによって入力された検索クエリ
  • 郵便アドレスは、計算することができますが、ユーザー入力で時間をかけて変更することもできますて
  • AddressFormは、これらの2つの関連コンポーネントの同期に保つための階層内の共通の祖先です.ユーザーがaddsResourcesでテキストを入力し始めると、ここでGeoCoderオートコンプリートAPIを照会し、addressInputを更新します.
    見るHERE Autocompletion JavaScript Demo クエリの必須パラメータが表示されます.app_id , and app_code . そのデモとは異なり、AxiosをHTTPクライアントとしてリクエストを行う.ここで定数変数を追加します.ここではAppChord CodeRoundを定義する必要があります.
    現在のアドレス形式は次のようになります.
    
    class AddressForm extends Component {
      constructor(props) {
        super(props);
    
        const address = this.getEmptyAddress();
        this.state = {
          'address': address,
          'query': '',
          'locationId': ''
        }
    
        this.onQuery = this.onQuery.bind(this);
      }
    
      onQuery(evt) {
        const query = evt.target.value;
        if (!query.length > 0) {
          const address = this.getEmptyAddress();
          return this.setState({
            'address': address,
            'query': '',
            'locationId': ''
            })
        }
    
        const self = this;
        axios.get('https://autocomplete.geocoder.api.here.com/6.2/suggest.json', {
          'params': {
            'app_id': APP_ID_HERE,
            'app_code': APP_CODE_HERE,
            'query': query,
            'maxresults': 1,
          }}).then(function (response) {
            const address = response.data.suggestions[0].address;
            const id = response.data.suggestions[0].locationId;
            self.setState({
              'address': address,
              'query': query,
              'locationId': id,
              });
          });
      }
    
      render() {
        return (
          <div class="container">
            <AddressSuggest
              query={this.state.query}
              onChange={this.onQuery}
              />
            <AddressInput
              street={this.state.address.street}
              city={this.state.address.city}
              state={this.state.address.state}
              postalCode={this.state.address.postalCode}
              country={this.state.address.country}
              />
            ...
          );
      }
    }
    
    
    GeoCoderオートコンプリートからの応答は、提案の配列が含まれています.情報の2つの貴重な作品が含まれてlocationId 我々は緯度と経度を得るためにIDによって完全なgeocoderルックアップをしたい場合.含まれてもaddress 詳細については、都市、国、通り、州、および郵便番号を表示するためのフォームです.

    逆データフロー


    AddressAssistコンポーネントのために、私たちがonChange={this.onQuery} . これは、このメソッドを下位レベルのコンポーネントにプッシュします.これらの下位レベルのコンポーネントは、ユーザーハンドラーに応答する必要があります.これは、このハンドラーへの参照をAddressAssistコンポーネントで見られるプロパティとして渡されたことを簡単にする必要があります.
    
    return (
        <AddressItem
          label="Address"
          value={this.props.query}
          onChange={this.props.onChange}
          placeholder="start typing" />
    );
    
    ユーザが入力した各文字がこのイベントをトリガーすることは注目に値する.各イベントは、GeoCoderオートコンプリートサービスへの要求をオフにするので、すぐに多くのトランザクションをラックすることができます.最終的な解決策は、これらのイベントがどのように処理されるか、あるいは変化することによって一度に1つ以上の提案の先読みを表示することのより効率的な使用をするかもしれませんmaxresults=10 .

    検証


    この点まで、我々はより少ないタイピングと誤りで正しいアドレスを推測するための提案として彼らの入力を使用することによって、ユーザーを助けました.一旦アドレスが入力されるならば、現在、我々はそれをチェックしたいです.我々のチェックとクリアボタンの動作を実装する必要がありますHERE Geocoder .
    まず、結果を含めるためにレンダリングされた要素を変更しますonClick イベントコールバック.
    { result }
    <button type="submit" className="btn btn-primary" onClick={this.onCheck}>Check</button>
    <button type="submit" className="btn btn-outline-secondary" onClick={this.onClear}>Clear</button>
    
    また、すべてのイベントハンドラがコンストラクタにバインドされていることを確認します.これは確かにthis は参考文献です.それから、これらのケースごとに定義されたメソッドがあります.
    
    // User has entered something in address suggest field
    this.onQuery = this.onQuery.bind(this);
    // User has entered something in address field
    this.onAddressChange = this.onAddressChange.bind(this);
    // User has clicked the check button
    this.onCheck = this.onCheck.bind(this);
    // User has clicked the clear button
    this.onClear = this.onClear.bind(this);
    
    クリアハンドラはかなり簡単です、ちょうど呼び出しsetState() コンストラクタが最初に動くとき、すべてを初期状態に戻すために.チェックハンドラは、大いに関与します.少し見てみましょう.この最初のセクションでは、geocoderサービスのパラメーターを初期化します.GeoCoderオートコンプリートを使用して適切なアドレスを見つける場合、我々はすでに使用できるLocationIdを持つ必要があります.我々がそれを持たないか、ユーザーがいろいろなフィールドにテキストを入力したならば、我々はどんな詳細も提供されている検索ストリングを構築します.
    
    onCheck(evt) {
      let params = {
        'app_id': APP_ID_HERE,
        'app_code': APP_CODE_HERE
      }
    
      if (this.state.locationId.length > 0) {
        params['locationId'] = this.state.locationId;
      } else {
        params['searchtext'] = this.state.address.street
          + this.state.address.city
          + this.state.address.state
          + this.state.address.postalCode
          + this.state.address.country
      }
      ...
    }
    
    
    パラメータを適切に使用すると、再びGeoCoder REST APIから応答を取得するためにaxiosを使用します.我々が一致する位置で約束された反応を取り戻すならば、我々は適切な成功またはエラー状況に状態をセットすることができます.
    
    onCheck(evt) {
      ...
    
      const self = this;
      axios.get('https://geocoder.api.here.com/6.2/geocode.json',
        { 'params': params }
      ).then(function(response) {
        const view = response.data.Response.View
        if (view.length > 0 && view[0].Result.length > 0) {
          const location = view[0].Result[0].Location;
    
          self.setState({
            'isChecked': 'true',
            'coords': {
                'lat': location.DisplayPosition.Latitude,
                'lon': location.DisplayPosition.Longitude
            },
            'address': {
              'street': location.Address.HouseNumber + ' ' + location.Address.Street,
              'city': location.Address.City,
              'state': location.Address.State,
              'postalCode': location.Address.PostalCode,
              'country': location.Address.Country
            }});
        } else {
          self.setState(
            'isChecked': true,
            'coords': null
            );
        }
    
      })
      ...
    }
    
    
    緯度と経度だけを得ることは最高の指標ではないので、アドレスが有効かどうか評価するためにマッチレベル、マッチタイプ、およびmatchqualityを見ることも重要です.
    
    "Result": [
              {
                "Relevance": 1,
                "MatchLevel": "houseNumber",
                "MatchQuality": {
                  "State": 1,
                  "City": 1,
                  "Street": [
                    1
                  ],
                  "HouseNumber": 1
                },
                "MatchType": "pointAddress",
                ...
    
    
    このようなアドレスの詳細についてはGeocoder Search Response ドキュメント.
    完全なソースリストのために、githubリポジトリをチェックしてくださいHERE-react-address-validation .

    概要


    このデモでは、ここでGeoCoderオートコンプリートAPIを使用してスマートアドレスフォームを構築できるように、Responseでコンポーネントを作成する方法を検討しました.また、私たちは私たちの試合の品質をテストするために緯度と経度を取得するためにここにGeocoder APIを使用していくつかの追加検証を行った.配達可能性のための通りアドレス検証は複雑な主題でありえます、しかし、これがあなたを始めることを望みます.
    クライアント側のアドレスバリデーションを行うには他にも多くの方法があります.ここでは、GeoCoderをコンポーネントとして使用する方法を見ることは、より良いユーザーエクスペリエンスにとって価値があることを願っています.他のライブラリを使うならFormik , react-final-form or informed そして、どのように反応によってアドレス検証をするかについての他の考えがあります.