UnsplashAPIを使用してReactで写真検索アプリを構築する方法

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

著者はCOVID-19救済基金を選択し、 Write forDOnationsプログラムの一環として寄付を受け取りました。

序章

StackOverflow 2020 Developer Survey によると、Reactは最も人気のあるJavaScriptフレームワークの1つであり、ウェブアプリのビューを効率的に変更するなど、多くの理由があります。 Virtual DOM を使用して、再利用可能、構成可能、およびステートフルなコンポーネントを使用して、スケーラビリティなどを向上させます。 初心者のReact開発者は、実際のアプリケーションで使用するために知識を活用する経験を必要とすることがよくあります。 このチュートリアルでは、 Reactフックの使用方法、 useState()の使用方法、およびReactでAPI呼び出しを行う方法を紹介します。

この記事では、 UnsplashAPIを使用してReactで写真検索アプリケーションを構築する手順を説明します。 Unsplashは現在、最も使用され人気のある写真検索エンジンの1つであり、プロジェクトやアプリケーションを構築する際の優れたデータプロバイダーになる可能性があります。

このチュートリアルを終了すると、ReactHooksを使用してUnsplashAPIをクエリする実用的なアプリケーションができあがります。 このプロジェクトは、同じプログラミングロジックを再利用し、API呼び出しを含む他のプロジェクトを構築するためのベースとして使用できるため、定型文としても機能します。 写真検索アプリケーションには、次のように検索バーとレンダリングされた結果が含まれます。

完全なコードを確認したい場合は、 DigitalOceanCommunityGitHubリポジトリをご覧ください。

前提条件

このガイドに従うために:

ステップ1—空のプロジェクトを作成する

このステップでは、 Create React App を使用します。これにより、手動で構成することなく、最初のプロジェクトが実行されます。 プロジェクトディレクトリで、次のコマンドを実行します。

npx create-react-app react-photo-search

このコマンドは、react-photo-searchという名前のフォルダーを作成し、ReactWebアプリケーションが機能するために必要なすべてのファイルと構成を含めます。

cdコマンドを使用してディレクトリを変更し、次のコマンドを実行してこのフォルダ内に移動します。

cd react-photo-search

次に、次のコマンドを実行して開発サーバーを起動します。

npm start

この開始スクリプトの詳細については、 Create ReactAppを使用してReactプロジェクトをセットアップする方法を確認してください。

次に、Webブラウザで http:// localhost:3000 に移動します。リモートサーバーからこれを実行している場合は、http://your_domain:3000に移動します。

Reactテンプレートがあります:

先に進む前に、ファイルをクリーンアップする必要があります。 Create React Appには不要なサンプルコードが付属しており、コードの保守性を確保するためにプロジェクトをビルドする前に削除する必要があります。

npm startによって既に使用されているため、別の端末を開く必要があります。

次のコマンドを実行して、index.cssのデフォルトのスタイルを削除します。

rm src/index.css

次に、次のコマンドを使用して、コードエディタでindex.jsを開きます。

nano src/index.js

index.cssを削除したので、index.jsからimport './index.css';を削除します。

import ./index.cssを削除すると、index.jsはこれと同じようになります。

react-photo-search / src / index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

ファイルを保存して終了します。

次に、ターミナルで次のコマンドを実行して、Reactロゴを削除します。

rm src/logo.svg

次のコマンドでApp.cssを開きます。

nano src/App.css

App.cssからすべてを削除し、ファイルを保存して終了します。 これは、ステップ3で新しいスタイルで更新します。

次のコマンドでsrc/App.jsを開きます。

nano src/App.js

次のステップは、import logo from './logo.svg';を削除し、App.jsファイルのclassName="App"を使用してdivからJSXを削除することです。 これにより、テンプレートのHTML要素が削除されます。

App.jsを次のように変更します。

react-photo-search / src / App.js

import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
         
    </div>
  );
}

export default App;

http://localhost:3000は空白になります。

これで、Reactアプリが初期化され、そこからサンプルコードが削除されました。 次に、Unsplash Developerダッシュボードで新しいアプリケーションを作成し、作成したアプリケーションのAccess KeySecret Keyをコピーして、UnsplashAPIにアクセスします。

ステップ2—UnsplashAPIクレデンシャルを取得する

このセクションでは、Unsplash開発者アカウントを申請し、このプロジェクトの新しいアプリケーションを作成し、このアプリケーションのAccess KeySecret KeyをコピーしてUnsplashAPIにアクセスします。 Unsplash APIはパブリックAPIではないため、このプロジェクトには独自のUnsplashAPIキーのセットが必要になります。

Unsplash Developer Home にアクセスして、開発者として登録してください。 Unsplashアカウントをすでに作成しているので、これは簡単なプロセスになります。

[開発者のスプラッシュ解除]ページで、開発者として登録ボタンをクリックします。

登録するためにあなたの資格情報を記入してください。

開発者として登録すると、開発者ダッシュボードに自動的にリダイレクトされます。 新しいアプリケーションをクリックします。

APIの使用とガイドラインに同意するよう求められます。 チェックボックスをクリックしてから、同意するボタンをクリックして先に進みます。

次に、アプリケーション情報を入力するように求められます。 アプリケーションに適切な名前と説明を付けて、アプリケーションの作成をクリックします。

これでアプリケーションが作成され、キーセクションのAccess KeySecret Keyにアクセスできるようになりました。 これらのキーを安全な場所にコピーします。 コードの後半でそれらが必要になります。

アプリケーション名の後にDemoタグが表示されることに注意してください。

このタグは、アプリケーションが開発モードにあり、リクエストが1時間あたり50に制限されていることを意味します。 個人的なプロジェクトの場合、これで十分ですが、本番環境に申し込むこともできます。これにより、リクエストの制限が1時間あたり5000に増えます。 適用する前に、APIガイドラインに従うことを忘れないでください。

このセクションでは、Unsplash APIアプリケーションを作成し、このプロジェクトに必要なキーを取得しました。 このプロジェクトでは、公式の Unsplash JavaScript Libraryunsplash-jsを使用して、APIをアプリに統合します。 次のステップでは、unsplash.jsをインストールし、CSSを追加してプロジェクトのスタイルを設定します。

ステップ3—依存関係のインストールとCSSの追加

次に、unsplash-jsパッケージを依存関係としてインストールし、カスタムCSSを追加してプロジェクトのスタイルを設定します。 行き詰まった場合は、このプロジェクトのDigitalOceanコミュニティリポジトリを参照してください。

npmパッケージマネージャーを使用してunsplash-jsライブラリをインストールするには、プロジェクトディレクトリで次のコマンドを実行します。

npm install unsplash-js

これは、このチュートリアルに従うためにインストールする必要がある唯一のライブラリです。 後で、 React-BootstrapSemantic UIReactなどのさまざまなReactユーザーインターフェイスライブラリを試すことができます。 このチュートリアルを実行した後、このプロジェクトを微調整してレイアウトを変更する場合は、これらのライブラリを追加する必要があります。

次に、Reactアプリのスタイルを設定します。 次のコマンドを実行して、App.cssを開きます。

nano src/App.css

このチュートリアルでは、CSSについて少しずつ説明します。

1つ目は、すべての要素を選択する*セレクターです。 次のコードを追加します。

react-photo-search / src / App.css

* {
  box-sizing: border-box;
  background-color: rgb(244, 244, 244);
  color: #333;
  font-size: 10px;
}

box-sizingプロパティは、要素の幅と高さの合計の計算方法を設定します。この場合、要素の幅と高さの計算に境界線とパディングを使用するようにブラウザに指示します。 背景色はbackground-colorを使用して設定し、値はrgb(244, 244, 244)で、背景に淡い白色を与えます。 colorは、要素のテキストの色を設定します。 ここでは、濃い灰色の色合いである16進コード#333が使用されています。 font-sizeはフォントのサイズを設定します。

次に、.Appブロックを追加します。これにより、className="App"の要素が選択されます。 デフォルトでは、親要素(className="App")にはある程度のマージンとパディングがあるため、次のコードは4辺すべてのmarginpadding0に設定します。

react-photo-search / src / App.css

* {
  box-sizing: border-box;
  background-color: rgb(244, 244, 244);
  color: #333;
  font-size: 10px;
}

.App {
  margin: 0;
  padding: 0;
}

次に、className="container"を使用してdiv要素にスタイルを追加します。 これは、divclassName="App"の子要素です。 タイトル、フォーム、ボタン、画像を含むすべてがこのdivに含まれます。

react-photo-search / src / App.css

* {
  box-sizing: border-box;
  background-color: rgb(244, 244, 244);
  color: #333;
  font-size: 10px;
}

.App {
  margin: 0;
  padding: 0;
}

.container {
  margin: 0 auto;
  max-width: 1000px;
  padding: 40px;
}

marginプロパティは、要素の周囲のスペースを定義するために使用されます。 marginは、toprightbottom、およびleftに設定できます。 値を1つだけ追加すると、この1つの値がすべてのtoprightbottom、およびleftに設定されます。 marginに2つの値を加算すると、最初の値はtopbottomに設定され、2番目の値はrightと[ X153X]。

margin: 0 auto;によると、topbottomには0のマージンがあり、leftrightにはautoがあります。 ]。 このautoは、ブラウザがコンテナに基づいてマージンを設定することを意味します。 これを理解する例は、親要素が100pxで、子要素が50pxの場合、left、およびrightのマージンは[ X163X] 。これにより、子要素が親要素の中央に配置されます。

max-widthは、要素のwidthの最大値(この場合は1000px)を設定します。 コンテンツが1000pxより大きい場合、要素のheightプロパティはそれに応じて変更されます。そうでない場合、max-widthは効果がありません。

上記のように、marginは要素の周囲のスペースを設定し、paddingは要素とそのコンテンツの間のスペースを設定します。 以前のコードは、container divとその中の要素の間に、4つの側面すべてから40pxのスペースがあることを意味します。

次に、アプリケーションのタイトルにスタイルを追加します。

react-photo-search / src / App.css

...
.container {
  margin: 0 auto;
  max-width: 1000px;
  padding: 40px;
}

.title {
  font-size: 4.4rem;
  font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS", sans-serif;
}

.titleは、アプリのタイトルである「ReactPhotoSearch」に対応します。 font-sizefont-familyの2つのプロパティのみが設定されます。 ここで、rem単位はfont-size値に使用されます。 rem値は、親要素に相対的なem値とは異なり、ルートhtml要素に相対的です。 ここで、4.4rem44px(4.4 x 10)を意味します。 この10pxによる乗算は、*セレクターを使用してすべての要素のフォントサイズを10pxに設定したためです。 font-familyは要素のフォントを指定します。 フォールバックシステムとして機能するためにコードで渡される多くの値があります。 ブラウザが最初のフォントを提供しない場合は、次のフォントが設定されます。

次は.formCSSブロックで、画像の検索に使用されるフォームが含まれています。 これには、入力検索フィールド、ボタン、およびラベルが含まれます。

react-photo-search / src / App.css

...
.title {
  font-size: 4.4rem;
  font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS", sans-serif;
}

.form {
  display: grid;
}

ここでは、displayプロパティのみが設定されています。 このプロパティは、要素の表示動作を指定します。 gridflexblockinlineなどのさまざまな値を取ることができます。 gridは、要素をブロックレベルとして表示し、グリッドモデルに従ってコンテンツをレンダリングします。

次は.label.inputCSSブロックです。

react-photo-search / src / App.css

...
.form {
  display: grid;
}

.label {
  font-size: 3rem;
  margin-bottom: 1rem;
}

.input {
  font-size: 1.6rem;
  padding: 0.5rem 2rem;
  line-height: 2.8rem;
  border-radius: 20px;
  background-color: white;
  margin-bottom: 1rem;
}

font-sizepaddingbackground-colormargin-bottomについてはすでに説明しましたので、line-heightborder-radiusについて説明します。 border-radiusは、要素の角の半径を定義します。 ここでは、値は20pxに設定されており、4辺すべてに使用されます。 border-radius50%に設定すると、正方形の要素を楕円形にすることができます。 line-heightは線の高さを指定し、2.8remまたは28pxに設定されています。

次は.buttonCSSブロックで、Searchボタンのスタイルを設定します。

react-photo-search / src / App.css

...
.input {
  font-size: 1.6rem;
  padding: 0.5rem 2rem;
  line-height: 2.8rem;
  border-radius: 20px;
  background-color: white;
  margin-bottom: 1rem;
}

.button {
  background-color: rgba(0, 0, 0, 0.75);
  color: white;
  padding: 1rem 2rem;
  border: 1px solid rgba(0, 0, 0, 0.75);
  border-radius: 20px;
  font-size: 1.4rem;
  cursor: pointer;
  transition: background-color 250ms;
}

background-colorcolorpaddingborder-radius、およびfont-sizeについてはすでに説明しました。 borderは、要素の境界線のスタイル、幅、および色を設定します。 ここで、borderは、border-widthborder-style、およびborder-colorの省略形プロパティとして使用されます。 このコードは、検索ボタンの周りに1pxの黒一色の境界線を追加します。 cursorは、要素の上を指すときのマウスカーソルを指定します。

次は、.buttonで使用される:hoverセレクターです。

react-photo-search / src / App.css

...
.button {
  background-color: rgba(0, 0, 0, 0.75);
  color: white;
  padding: 1rem 2rem;
  border: 1px solid rgba(0, 0, 0, 0.75);
  border-radius: 20px;
  font-size: 1.4rem;
  cursor: pointer;
  transition: background-color 250ms;
}

.button:hover {
  background-color: rgba(0, 0, 0, 0.85);
}

これは、マウスを.button要素に合わせると、背景色が変わることを意味します。

次のCSSブロックは.card-listで、これはdivclassName="card-list"に対応します。 このdivは、その中のすべての画像を表示します。

react-photo-search / src / App.css

...
.button:hover {
  background-color: rgba(0, 0, 0, 0.85);
}

.card-list {
  column-count: 3;
}

column-countは、要素内で渡される値に従って要素を列に分割します。 このコードは、card-list divを3つの列に分割し、画像はこれらの3つの列内に表示されます。

次は.card.card--imageCSSブロックです。 .cardは、内部に画像がある個々のdivを指し、.card--imageはこの画像のclassNameです。

react-photo-search / src / App.css

...
.card-list {
  column-count: 3;
}

.card {
    margin-bottom: 1rem;
    display: flex;
}

.card--image {
    flex: 100%;
    margin-top: 1rem;
    border-radius: 10px;
}

margindisplay、およびborder-radiusについてはすでに説明しました。 .cardでは、displayflexに設定されます。これは、要素がブロック要素のように動作し、フレックスボックスモデルに従って表示が設定されることを意味します。 ]。 省略形のプロパティflex:100%;を使用して、flex-growflex-shrink、およびflex-basisの値を設定します。 詳細については、Mozilla DeveloperNetworkを読むことができます。

最後のCSSブロックには、メディアクエリが含まれます。 @mediaルールを使用すると、さまざまなメディアタイプ/デバイスにさまざまなスタイルを適用できます。

react-photo-search / src / App.css

...
.card--image {
    flex: 100%;
    margin-top: 1rem;
    border-radius: 10px;
}

@media (min-width: 768px) {
  .form {
    grid-template-columns: auto 1fr auto;
    grid-gap: 1rem;
    align-items: center;
  }
  .input {
    margin-bottom: 0;
  }
}

@media only screen and (max-width: 600px) {
    .card-list {
        column-count: 1;
    }
}

このコードによると、ブラウザウィンドウが600px以下の場合、column-count3から1に変わります(ほとんどのモバイルデバイスに適用可能)。 これは、@mediaルールでmax-widthプロパティを使用しました。 その前のコードはmin-widthを使用しており、幅が768px以上の場合、@mediaルール内の要素のスタイルを変更します。

grid-template-columnsは、グリッドモデルの列を指定するために使用されます。 列の数は、渡される値の数と同じであり、コード( auto 1fr auto)によると3つです。 1番目と3番目のグリッド要素のサイズは、コンテナのサイズまたはコンテンツのサイズに応じて異なります。 2番目の要素には1fr(フラクショナル単位)、つまり1番目と3番目の要素が占有された後に残ったスペースがサイズに応じて与えられます。 これらの3つの要素は、カメラの絵文字、検索入力フィールド、および検索ボタンになります。 絵文字とボタンがサイズに応じてスペースをとった後、残りの領域は検索入力フィールドに移動し、それに応じて幅が変更されます。

grid-gap: 1rem;は、2つのグリッド線の間に1remのスペースを作成します。 align-items:center;は、アイテムをコンテナの中央に配置します。

これで、アプリケーションのスタイリングが終了します。 保存してsrc/App.cssを終了します。 CSSファイル全体をまとめて表示したい場合は、このコードのGitHubリポジトリをご覧ください。

必要な依存関係をインストールし、プロジェクトのスタイル設定に必要なカスタムCSSを追加したので、次のセクションに進んで、プロジェクトのUIまたはレイアウトを設計できます。

ステップ4—ユーザーインターフェイスの設計

このセクションでは、プロジェクトのUIを設計します。 これには、見出し、ラベル、入力フィールド、ボタンなどの要素が含まれます。

次のコマンドでsrc/App.jsファイルを開きます。

nano src/App.js

プロジェクトに見出しを追加するには、App.js内にclassName="container"を含むdivを作成します。 このdivの中に、h1タグにclassName="title"を追加し、タグの中にReact Photo Searchと書き込みます。 これがタイトルの見出しになります。

react-photo-search / src / App.js

import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
      <div className="container">
        <h1 className="title">React Photo Search</h1>
      </div>
    </div>
  );
}

ファイルを保存して終了します。 ブラウザに、アプリにタイトルが表示されます。

次に、ユーザーからの入力を受け取るフォームを作成します。 このフォームは、入力テキストフィールドと送信ボタンで構成されます。

このために、<SearchPhotos />という名前の新しいコンポーネントを作成します。 別のコンポーネントを作成する必要はありませんが、このプロジェクトを開発するときに、コードをコンポーネントに分割すると、コードの記述と保守が容易になります。

srcフォルダーで、次のコマンドを使用してsearchPhotos.jsという名前の新しいファイルを作成して開きます。

nano src/searchPhotos.js

searchPhotos.js内で、<SearchPhotos />という名前の機能コンポーネントをエクスポートします。

react-photo-search / src / searchPhotos.js

import React from "react";

export default function SearchPhotos() {
  return (
    <>

    </>
  );
}

これは、searchPhotos.jsファイルに追加する必要のある機能コンポーネントの基本構造です。 このファイルを保存します。

次のステップは、App.jsSearchPhotosコンポーネントをインポートして使用することです。

新しいターミナルウィンドウで、App.jsを開きます。

nano src/App.js

次の強調表示された行をApp.jsに追加します。

react-photo-search / src / App.js

import React from "react";
import "./App.css";
import SearchPhotos from "./searchPhotos"

function App() {
  return (
    <div className="App">
      <div className="container">
        <h1 className="title">React Photo Search</h1>
        <SearchPhotos />

      </div>
    </div>
  );
}
export default App;

このファイルを保存します。

検索フォームを作成するには、formタグを使用し、その中にinputタグを使用して入力フィールドを作成し、buttonタグを使用してボタンを作成します。

要素にそれぞれのタグのclassNameを付けます。 これを行っている間に、スタイリングのためにカメラの絵文字が入ったラベルを追加します。

react-photo-search / src / searchPhotos.js

...
export default function SearchPhotos() {
  return (
    <>
      <form className="form"> 
        <label className="label" htmlFor="query"> 
          {" "}
          📷
        </label>
        <input
          type="text"
          name="query"
          className="input"
          placeholder={`Try "dog" or "apple"`}
        />
        <button type="submit" className="button">
          Search
        </button>
      </form>
    </>
  );
}

まず、className="form"を使用してform要素を作成し、その中にカメラの絵文字を使用してlabelを作成しました。 次に、検索クエリが文字列になるため、属性type="text"を持つinput要素が表示されます。 name="query"属性は、input要素の名前を指定し、className="input"は要素にスタイル設定のクラスを与え、検索バーのプレースホルダー値は[に設定されます。 X177X]。 formの最後の要素は、type="submit"を持つbuttonです。

ファイルを保存して終了します。 これで、アプリのタイトルの後に検索バーが表示されます。

アプリのUIが完成したので、最初にユーザーからの入力クエリを次のセクションに保存することで、機能の作業を開始できます。

ステップ5—検索クエリを使用して状態を設定する

このステップでは、状態React Hooks について学び、それらを使用してユーザー入力を保存します。

アプリケーションの基本構造を構築したので、Reactの側面について説明します。 フォームはありますが、まだ何も実行されていないため、最初に行うことは、検索バーから入力を取得してアクセスすることです。 あなたは州でこれを行うことができます。

コアとなる状態は、コンポーネントのプロパティ値を格納するために使用されるオブジェクトです。 状態が変化するたびに、コンポーネントは再レンダリングされます。 このアプリでは、検索ボタンがクリックされるたびに検索バーからの入力またはクエリを保存する状態が必要です。

お気づきかもしれませんが、このプロジェクトでは機能コンポーネントを使用しています。 これにより、Reactフックを使用して状態を管理できます。 フックは、クラスを記述せずに状態を定義するなどのReact機能を使用する関数です。 このチュートリアルでは、useState()フックを使用します。

最初に行うことは、searchPhotos.jsファイル内にuseStateをインポートすることです。

ファイルを開きます。

nano src/searchPhotos.js

searchPhotos.jsファイルの最初の行を次のように変更します。

react-photo-search / src / searchPhotos.js

import React, { useState } from "react";

export default function SearchPhotos() {
...

次に、useState()を実装します。 これは、useState()フックの構文です。

useState(initialState)

useState()は、現在の状態と、一般にアップデーター関数として知られている関数を返します。 これらを保存するには、配列の破棄を使用できます。

const [query, setQuery] = useState(initialState);

この例では、queryはコンポーネントの現在の状態を格納し、setQueryは状態を更新するために呼び出すことができる関数です。 initialStateは初期状態値を定義します。 用途に応じて、文字列、数値、配列、またはオブジェクトにすることができます。

プロジェクトでは、検索バーからの入力は文字列であるため、状態の初期値として空の文字列を使用します。

searchPhotos.jsファイルに、次のコード行を追加します。

react-photo-search / src / searchPhotos.js

...

export default function SearchPhotos() {
  const [query, setQuery] = useState("");
 
  return (
    <>
      <form className="form">
        <label className="label" htmlFor="query">
          {" "}
          📷
        </label>
...

次のステップは、入力テキストフィールドのvaluequeryに設定し、それにonChange()イベントを追加することです。 このonChange()イベントには関数があり、その中でsetQuery()を使用して状態を更新します。 入力文字列は、e.target.valueを使用して取得されます。

react-photo-search / src / searchPhotos.js

...
<input
    type="text"
    name="query"
    className="input"
    placeholder={`Try "dog" or "apple"`}
    value={query}
    onChange={(e) => setQuery(e.target.value)}
/>
...

これで、状態と入力フィールドの値が相互にリンクされ、この検索クエリを使用して画像を検索できます。

query内の検索バーからの入力を、テスト目的でリアルタイムに表示できます。 状態を定義した場所の直後にconsole.log(query)を追加します。

react-photo-search / src / searchPhotos.js

...
export default function SearchPhotos() {
   const [query, setQuery] = useState("");
   console.log(query);

  return (
    <>
    //
    </>
  );
}

ファイルを保存します。

これで、コンソール内に入力クエリを受け取ります。 ChromeF12またはFirefoxCtrl+Shift+Kを使用して、コンソールを開くことができます。

これで、searchPhotos.jsは次のようになります。

react-photo-search / src / searchPhotos.js

import React, { useState } from "react";
export default function SearchPhotos() {
  const [query, setQuery] = useState("");
  console.log(query);

  return (
    <>
      <form className="form">
        <label className="label" htmlFor="query">
          {" "}
          📷
        </label>
        <input
          type="text"
          name="query"
          className="input"
          placeholder={`Try "dog" or "apple"`}
          value={query}
          onChange={(e) => setQuery(e.target.value)}
        />
        <button type="submit" className="button">
          Search
        </button>
      </form>
    </>
  );
}

このセクションでは、状態とReactフックについて説明し、ユーザー入力をquery状態内のinputフィールドに保存しました。 次のセクションでは、この検索クエリを使用して画像を検索し、応答を別の状態に保存します。

ステップ6—スプラッシュを解除するためのAPIリクエストを作成する

次に、unsplash-jsライブラリを使用して、inputフィールドからのクエリを使用して画像を検索します。 応答は、picsという名前の別の状態に保存されます。

unsplash-jsライブラリはすでにインストールされているので、searchPhotos.jsファイルにインポートします。 前のセクションからconsole.log()ステートメントを削除することもできます。

react-photo-search / src / searchPhotos.js

import React, { useState } from "react";
import Unsplash, { toJson } from "unsplash-js";

...

toJsonは、unsplash-jsライブラリのヘルパー関数であり、応答をJSON形式に変換するために使用されます。 ヘルパー関数の詳細については、unsplash-jsGitHubページをご覧ください。

アプリでUnsplashを使用するには、次のようにnewキーワードを使用してインスタンスを作成します。

react-photo-search / src / searchPhotos.js

import React, { useState } from "react";
import Unsplash, { toJson } from "unsplash-js";

const unsplash = new Unsplash({
  accessKey: "your_Access_Key",
});

Unsplash Access Keyを貼り付けて、your_Access_Keyを置き換えます。これで、APIリクエストを行うことができます。

警告:APIまたはサービスのアクセスキーまたはクライアントIDを共有しないでください。 潜在的な悪意のある人物は、インターネット上でそれらを悪用する可能性があります。 このシナリオでは、サービスプロバイダーによってスパムとしてフラグが立てられる可能性のある異常な量の要求を行う可能性があり、これによりアプリケーションとアカウントが非アクティブ化される可能性があります。


次に、検索ボタンをクリックするとトリガーされる非同期関数を作成します。

queryの状態を定義した直後に、async関数を定義します。

react-photo-search / src / searchPhotos.js

...
export default function SearchPhotos() {
  const [query, setQuery] = useState("");

  const searchPhotos = async (e) => {
    e.preventDefault();
    console.log("Submitting the Form")
  };

ここで、e.preventDefault()は、検索ボタンがクリックされるたびにページの再読み込みを停止します。 この関数は、formタグ内のonSubmitイベントで渡すことができます。 これについて詳しくは、公式Reactドキュメントをご覧ください。

react-photo-search / src / searchPhotos.js

...
  return (
    <>
      <form className="form" onSubmit={searchPhotos}>
...

ファイルを保存します。 ここで、検索ボタンをクリックすると、コンソールにSubmitting the Formが表示されます。 コンソールで正常に応答した後、このconsole.log()を削除できます。

searchPhotos()関数内では、Unsplashインスタンス(unsplash)を使用します。 search方式で画像を検索できます。 そのための構文は次のとおりです。

search.photos(keyword, page, per_page, filters)

画像を検索するためのコードは次のとおりです。 searchPhotos()関数内に次のコードを追加します。

react-photo-search / src / searchPhotos.js

...
const searchPhotos = async (e) => {
  e.preventDefault();
  unsplash.search
    .photos(query)
    .then(toJson)
    .then((json) => {
      console.log(json);
    });
};
...

まず、unsplash.searchを使用してから、検索対象(この場合はphotos)を指定します。 usersまたはcollectionsを検索することもできます。 photosは、検索するキーワードとして最初に必要な引数を取ります。これはqueryです。 オプションの引数を使用して、ページ、ページごとの応答、画像の向きなどを指定することもできます。 このチュートリアルでは、pageおよびper_page引数のみが必要であり、Unsplashから取得する応答項目を制限します。

photosで提供できるすべての引数は次のとおりです。

口論 タイプ オプション/必須 デフォルト
keyword ストリング 必須
page 番号 オプション
per_page 番号 オプション 10
filters 物体 オプション
filters.orientation ストリング オプション
filters.collections 配列 オプション

詳細については、unsplash-jsGitHubページをご覧ください。

toJsonメソッドを使用して応答をJSONに変換し、最後にconsole.log()応答を使用して、API要求がエラーなしで行われたことをテストします。 次の手順で、このconsole .log ()を削除します。

ファイルを保存します。 次に、コンソールを開き、検索ボタンをクリックします。 次のような応答JSONが見つかります。

{
  "results": [{
     "description": "Pink Wall Full of Dogs",
     "alt_description": "litter of dogs fall in line beside wall",
     "urls": {
           "raw": "https://images.unsplash.com/photo-1529472119196-cb724127a98e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjE0MTQxN30",
           "full": "https://images.unsplash.com/photo-1529472119196-cb724127a98e?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0MTQxN30",
           "regular": "https://images.unsplash.com/photo-1529472119196-cb724127a98e?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjE0MTQxN30",
           "small": "https://images.unsplash.com/photo-1529472119196-cb724127a98e?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0MTQxN30",
           "thumb": "https://images.unsplash.com/photo-1529472119196-cb724127a98e?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&ixid=eyJhcHBfaWQiOjE0MTQxN30"
                },
    ...
}

Unsplash APIから正常な応答が見つかったら、console.log()ステートメントを削除またはコメント化できます。これは、コードが正常に機能していることを意味します。 このアプリは"urls"フィールドが画像のソースになるためです。

unsplash-jsライブラリを使用して検索ボタンがクリックされたときに、ユーザーからのクエリを使用して画像を検索しました。 次に、応答をpicsという名前の別の状態に保存し、この状態内の要素をマッピングして画像を表示します。

ステップ7—Webページに画像を表示する

この最後のセクションでは、Unsplash APIからの応答をpicsという名前の別の状態に保存し、この状態の要素にマップしてWebページに画像を表示します。

画像を表示するには、応答JSONにアクセスする必要があります。そのためには、別の状態が必要になります。 以前の状態queryには、UnsplashAPIへのリクエストを行うために使用されたユーザーからのクエリが保存されていました。 この状態picsには、UnsplashAPIから取得した画像応答が保存されます。

searchPhotos.jsで、次のような別の状態を定義します。

react-photo-search / src / searchPhotos.js

...
  const [query, setQuery] = useState("");
  const [pics, setPics] = useState([]);
...

この状態は空のarrayで初期化されており、すべての応答はこの状態内のオブジェクトとして保存されます。 つまり、これはオブジェクトの配列です。

この状態をJSONで更新するには、unsplashAPIリクエスト内でsetPicsを使用します。

react-photo-search / src / searchPhotos.js

...
    unsplash.search
      .photos(query, 1, 20)
      .then(toJson)
      .then((json) => {
        setPics(json.results);
  });
...

これで、新しいクエリを検索するたびに、この状態がそれに応じて更新されます。

次に、formタグが終了する直後にclassName="card-list"を使用してdivを作成します。

react-photo-search / src / searchPhotos.js

...
        <button type="submit" className="button">
          Search
        </button>
      </form>
      <div className="card-list">
      </div>
    </>
  );
}

このdiv内で、状態をマッピングし、画像のidを表示します。

react-photo-search / src / searchPhotos.js

...
        <button type="submit" className="button">
          Search
        </button>
      </form>
      <div className="card-list">
        {pics.map((pic) => pic.id )}
      </div>
    </>
  );
}

最初に{}を使用してJavaScript式を渡し、その中で .map()メソッドを州で使用します。

ファイルを保存します。 ここで検索すると、Webページ上のさまざまなオブジェクトに関連付けられているidが表示されます。

これは厄介ですが、これはアプリケーションが機能していることも意味します。

pic.idを表示する代わりに、map関数内でJSXを開き、className="card"を使用して新しいdivを作成します。 これは、個々の画像のコンテナになります。

react-photo-search / src / searchPhotos.js

...
        <button type="submit" className="button">
          Search
        </button>
      </form>
      <div className="card-list">
        {
          pics.map((pic) => <div className="card"></div>);
        }
      </div>
    </>
  );
}

これで、このdiv内に画像を表示できます。

react-photo-search / src / searchPhotos.js

...
        <button type="submit" className="button">
          Search
        </button>
      </form>
      <div className="card-list">
        {
          pics.map((pic) => 
            <div className="card">
              <img
                className="card--image"
                alt={pic.alt_description}
                src={pic.urls.full}
                width="50%"
                height="50%"
              ></img>
            </div>);
        }
      </div>
    </>
  );
}

戻って応答JSONを見ると、別の種類の情報が見つかります。 "urls"には画像へのパスが含まれているため、ここでpic.urls.fullは画像への実際のパスであり、pic.alt_descriptionは画像の代替説明です。

"urls"内には、次のようなさまざまなデータを提供するさまざまなフィールドがあります。

raw:ユーザーが撮影した実際のRAW画像。 full.jpg形式のRaw画像。 regular:実用に最適、width=1080pxsmall:低速のインターネット速度に最適です。width=400pxthumb:画像のサムネイルバージョンwidth=200px

このチュートリアルでは、fullを使用していますが、他のタイプを試すこともできます。 また、デフォルトのheightおよびwidthを画像に指定しました。

ファイルを保存します。

アプリケーションはほぼ完成しています。 今すぐ検索すると、アプリケーションの動作を確認できます。 しかし、まだ小さなコード行が残っています。 画像を検索してブラウザでコンソールに移動すると、警告が表示されます。

Web consoleWarning: Each child in a list should have a unique "key" prop.

これを修正するには、画像のidを使用して、すべての子に一意のkeyを渡します。 このkey prop は、リスト内の各子のIDをReactに明示的に通知します。 これにより、子がレンダリング間で状態を失うのを防ぐこともできます。

react-photo-search / src / searchPhotos.js

...
      <div className="card-list">
        {pics.map((pic) =>
          <div className="card" key={pic.id}>
            <img
              className="card--image"
              alt={pic.alt_description}
              src={pic.urls.full}
              width="50%"
              height="50%"
            ></img>
          </div>)};
      </div>
    </>
  );
}

unsplash.search.photos()に対応する引数を渡すことで、表示する画像の数を調整できます。

ファイルを保存して終了します。 これで、写真検索アプリが機能するようになります。

このセクションでは、Unsplash APIからの応答をpics状態に保存し、picsの要素にマッピングして画像を表示しました。

結論

このチュートリアルでは、UnsplashAPIを使用してReactPhotoSearchアプリを開発しました。 プロジェクトを構築する際に、チュートリアルでは、React Hooksの使用方法、APIのクエリ方法、およびユーザーインターフェイスのスタイル設定方法について説明しました。

このアプリケーションを拡張するためにできることはたくさんあります。 たとえば、ランダムボタンを追加してランダムな画像を表示したり、チェックボックスを作成して写真の検索とユーザーの好みに応じて写真を投稿したユーザーを切り替えたり、無限スクロールを追加したりできます。 ]より多くの画像などを表示します。 同じコンセプトを使用して、 Hacker NewsAPIなどのAPIリクエストを含む他のプロジェクトを作成することもできます。

Reactチュートリアルをもっと見たい場合は、Reactトピックページをチェックしてください。