如何使用 Unsplash API 使用 React 构建照片搜索应用程序

作者选择了COVID-19 救济基金来接受捐赠,作为Write for DOnations计划的一部分。

介绍

根据StackOverflow 2020 开发人员调查React是最受欢迎的JavaScript框架之一,其原因有很多,例如使用Virtual DOM有效更改 Web 应用程序视图,使用可重用、可组合和有状态的组件来提高可扩展性,以及更多的。初学者 React 开发人员通常需要将他们的知识用于实际应用程序的经验。本教程将通过向您展示如何在React中使用React Hooks、使用useState()和进行 API 调用来为您提供这种体验

本文将讨论使用Unsplash API使用 React 构建照片搜索应用程序的分步过程Unsplash 是目前最常用和最流行的照片搜索引擎之一,在构建项目和应用程序时可以成为一个很好的数据提供者。

在本教程结束时,您将拥有一个使用 React Hooks 查询 Unsplash API 的工作应用程序。该项目还可以充当样板,因为您可以重用相同的编程逻辑,并将其用作构建涉及 API 调用的其他项目的基础。您的照片搜索应用程序将包括一个搜索栏和呈现的结果,如下所示:

照片搜索应用程序

如果您想查看完整代码,请查看DigitalOcean 社区 GitHub 存储库

先决条件

为了遵循本指南:

第 1 步 – 创建一个空项目

在这一步中,您将使用Create React App,它将在不进行任何手动配置的情况下运行初始项目。在您的项目目录中,运行以下命令。

  • npx create-react-app react-photo-search

此命令将创建一个文件夹,react-photo-search其中包含用于工作的 React Web 应用程序的所有必要文件和配置。

使用该cd命令更改目录并通过运行以下命令进入该文件夹:

  • cd react-photo-search

接下来,通过运行以下命令启动开发服务器:

  • npm start

有关此启动脚本的信息,请查看如何使用 Create React App 设置 React 项目

接下来,转到http://localhost:3000Web 浏览器,或者如果您从远程服务器运行它,则.http://your_domain:3000

你会发现 React 模板:

带有 React 徽标的 React 起始模板

在进一步移动之前,您必须清理文件。Create React App 附带了一些不需要的示例代码,应该在构建项目之前将其删除以确保代码可维护性。

您现在需要打开另一个终端,因为一个终端已经被npm start.

index.css通过运行以下命令删除默认样式

  • rm src/index.css

接下来,index.js使用以下命令在代码编辑器中打开

  • nano src/index.js

由于您已删除index.css,请import './index.css';从 中删除index.js

index.js完成删除后import ./index.css将与此类似

反应照片搜索/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';并取出JSXdivclassName="App"App.js文件中。这将删除模板的 HTML 元素。

修改App.js 成这样:

反应照片搜索/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以访问 Unsplash API。

第 2 步 – 获取 Unsplash API 凭证

在本节中,您将申请一个 Unsplash 开发者帐户,为此项目创建一个新应用程序,并复制该应用程序Access KeySecret Key以获得对 Unsplash API 的访问权限。由于 Unsplash API 不是公共 API,因此您需要为该项目设置自己的 Unsplash API 密钥集。

前往Unsplash 开发人员主页并注册为开发人员。由于您已经创建了一个 Unsplash 帐户,这将是一个快速的过程。

在 Unsplash Developer 页面上,单击Register as a developer按钮。

Unsplash 开发者页面

填写您的凭据进行注册。

注册为开发人员后,您将被自动重定向到您的开发人员仪表板单击“新建应用程序”

带有新应用程序的 Unsplash 开发人员仪表板

您将被要求接受API 使用和指南单击复选框,然后单击接受条款按钮以进一步进行:

Unsplash API 使用和指南

然后将提示您提供您的应用程序信息为您的应用程序提供适当的名称和描述,然后单击创建应用程序

Unsplash 应用程序信息弹出窗口

有了这个,你已经创建了一个应用程序,现在可以访问Access KeySecret Key部分。将这些密钥复制到安全位置;您稍后将在代码中需要它们。

Unsplash 应用程序页面的键部分

请注意,您将在应用程序名称后看到一个Demo标签:

Unsplash 应用程序名称旁边的 Demottag

此标记表示您的应用程序处于开发模式并且请求限制为每小时 50 个。对于个人项目,这已经绰绰有余,但您也可以申请生产,这会将请求限制增加到每小时 5000 个。请记住在申请前遵循API 指南

在本节中,您创建了一个 Unsplash API 应用程序并获得了该项目所需的密钥。对于这个项目,你会使用官方Unsplash JavaScript库unsplash-js到API与您的应用程序集成。unsplash.js在下一步中,您将安装并添加 CSS 以设置项目的样式。

第 3 步 – 安装依赖项并添加 CSS

您现在将安装该unsplash-js包作为依赖项并添加自定义 CSS 以设置您的项目样式。如果您遇到任何问题,请参阅此项目DigitalOcean 社区存储库

unsplash-js使用npm 包管理器安装库,请在项目目录中运行以下命令:

  • npm install unsplash-js

这是您按照本教程需要安装的唯一库;稍后,您可以尝试使用不同的 React 用户界面库,例如React-BootstrapSemantic UI React等。如果在遵循本教程之后,您想要调整此项目并更改其布局,则应该添加这些库。

接下来,您将设置 React 应用程序的样式。App.css通过运行以下命令打开

  • nano src/App.css

本教程将逐个讨论 CSS。

首先是*选择器,它选择所有元素。添加以下代码:

反应照片搜索/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设置元素文本的颜色;这里#333使用了十六进制代码,它是一种深灰色阴影。font-size设置字体的大小。

接下来,添加.App块,它选择带有className="App". 默认情况下,父元素 ( className="App") 有一些边距和填充,因此以下代码将所有四个边的margin设置padding0

反应照片搜索/src/App.css
* {
  box-sizing: border-box;
  background-color: rgb(244, 244, 244);
  color: #333;
  font-size: 10px;
}

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

接下来,div使用className="container". 这是divwith的子元素className="App"包括标题、表单、按钮和图像在内的所有内容都将包含在此div

反应照片搜索/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如果只添加一个值,那么这一个值将所有设置toprightbottom,和left如果在 中添加两个值margin,则第一个值将设置为topand bottom,第二个值将设置为rightand left

margin: 0 auto;top并且bottom0利润,而leftrightautoauto意味着浏览器将根据容器设置边距。理解这一点的一个示例是,如果父元素是100px,子元素是50px,则leftright边距将是25px,这将使子元素在父元素内居中。

max-width设置width元素的最大值,在本例中为1000px如果内容大于1000px,则height元素属性会相应改变,否则max-width无效。

如上所述,margin设置元素周围的空间,同时padding设置元素与其内容之间的空间。较早的代码意味着它container div内部和 元素40px之间将有四个边的空间。

接下来,为应用程序的标题添加样式:

反应照片搜索/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对应于您的应用程序的标题,即“React Photo Search”。只设置了两个属性,即font-sizefont-family此处,rem单位用于font-size值。rem值是相对于根html元素的,不像em值是相对于父元素的。这里的4.4rem意思是44px(4.4 x 10)。这种乘法10px是因为您将所有元素的字体大小设置为10px使用*选择器。font-family指定元素的字体。代码中传递了许多值作为回退系统;如果浏览器不提供第一种字体,则设置下一种字体。

接下来是.formCSS 块,其中包含将用于搜索图像的表单。这包括输入搜索字段、按钮和标签。

反应照片搜索/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 块:

反应照片搜索/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-size, padding, background-color, 和margin-bottom,所以让我们讨论line-heightborder-radiusborder-radius定义元素角的半径。此处将该值设置为20px,将用于所有四个边。设置border-radius50%可以将方形元素变成椭圆形。line-height指定行的高度,设置为2.8rem28px

接下来是.buttonCSS 块,它设置搜索按钮的样式

反应照片搜索/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-sizeborder设置元素边框的样式、宽度和颜色。这里border被用作速记属性border-widthborder-styleborder-color此代码在“搜索”按钮周围添加了 1 像素的纯黑色边框cursor指定鼠标指针指向元素时的光标。

接下来是:hover选择器,它用于.button.

反应照片搜索/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,它对应于divwith className="card-list"div将显示其中的所有图像:

反应照片搜索/src/App.css
...
.button:hover {
  background-color: rgba(0, 0, 0, 0.85);
}

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

column-count根据在元素内部传递的值将元素划分为列。此代码将分为card-list div三列,图像将显示在这三列中。

接下来是.card.card--imageCSS 块。.carddiv其中包含图像的个人,并且.card--imageclassName此图像的 :

反应照片搜索/src/App.css
...
.card-list {
  column-count: 3;
}

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

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

我们已经讨论过margindisplayborder-radius.card,display设置为flex,这意味着元素将表现得像块元素,并且显示将根据flexbox 模型设置通过使用速记属性flex:100%;,您可以设置值flex-growflex-shrinkflex-basis您可以在 Mozilla Developer Network阅读更多相关信息

最后的 CSS 块涉及媒体查询通过使用该@media规则,您可以为不同的媒体类型/设备应用不同的样式:

反应照片搜索/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;
    }
}

根据这个代码,column-count将从改变31当浏览器窗口是600px以下(适用于多数移动设备)。这将max-width属性与@media规则一起使用。之前的代码使用min-width@media当宽度为768px或更大改变规则内元素的样式

grid-template-columns用于指定网格模型中的列。列数等于传递的值数,根据代码(auto 1fr auto为三第一个和第三个网格元素的大小将取决于它们的容器大小或内容的大小。将给出第二个元素1fr(Fractional Unit),或根据它们的大小占用第一个和第三个元素后留下的空间。这三个元素将是相机表情符号、搜索输入字段和搜索按钮。表情符号和按钮根据其大小占用空间后,其余区域将进入搜索输入字段,并相应地更改其宽度。

grid-gap: 1rem;1rem在两条网格线之间创建一个空间align-items:center;将项目放置在容器的中心。

这样就完成了应用程序的样式。保存并退出src/App.css如果您想一起查看整个 CSS 文件,请查看此代码GitHub 存储库

现在您已经安装了必要的依赖项并添加了为您的项目设置样式所需的自定义 CSS,您可以前进到下一部分并设计项目的 UI 或布局。

第 4 步 – 设计用户界面

在本节中,您将设计项目的 UI。这将包括标题、标签、输入字段和按钮等元素。

src/App.js使用以下命令打开文件:

  • nano src/App.js

要将标题添加到您的项目中,创建一个divclassName="container"你的里面App.js在这个里面div添加一个h1带有 的标签className="title"并写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 />

反应照片搜索/src/searchPhotos.js
import React from "react";

export default function SearchPhotos() {
  return (
    <>

    </>
  );
}

这是您需要添加到searchPhotos.js文件中的功能组件的基本结构保存此文件。

下一步是导入和使用SearchPhotos的组件App.js

在新的终端窗口中,打开App.js

  • nano src/App.js

将以下突出显示的行添加到App.js

反应照片搜索/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各自的标签。在执行此操作时,添加一个带有相机表情符号的标签以进行样式设置:

反应照片搜索/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>
    </>
  );
}

首先,您创建了一个form带有 a元素className="form",并在其中创建了一个label带有相机表情符号的a元素然后是input带有属性元素type="text",因为搜索查询将是一个字符串name="query"属性指定input元素的名称,为元素className="input"提供样式类,搜索栏的占位符值设置为Try "dog" or "apple"中的最后一个元素formbutton带有type="submit".

保存并退出文件。您的应用现在将在标题后面有一个搜索栏:

带有搜索栏和“尝试“狗”或“苹果”的占位符文本的应用程序

现在应用程序的 UI 已经完成,您可以通过在下一部分中首先存储来自用户的输入查询来开始处理功能。

第 5 步 – 使用搜索查询设置状态

在这一步中,您将了解状态React Hooks,然后使用它们来存储用户输入。

现在您已经构建了应用程序的基本结构,我们可以讨论 React 方面的事情。您有一个表单,但它还没有做任何事情,所以首先要做的是从搜索栏中获取输入并访问它。你可以用状态来做到这一点。

在他们的核心国家是对象是用于存储组件的属性值。每次状态改变时,组件都会重新渲染。对于此应用程序,您需要一个状态,以便在单击搜索”按钮时存储来自搜索栏中的输入或查询

您可能已经注意到的一件事是该项目正在使用功能组件。这允许您使用 React Hooks 来管理状态。Hook 是使用 React 功能的函数,例如无需编写类即可定义状态。在本教程中,您将使用useState()Hook。

首先要做的是useStatesearchPhotos.js文件中导入

打开文件:

  • nano src/searchPhotos.js

searchPhotos.js文件的第一行修改为以下内容:

反应照片搜索/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文件中,添加以下代码行:

反应照片搜索/src/searchPhotos.js
...

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

  return (
    <>
      <form className="form">
        <label className="label" htmlFor="query">
          {" "}
          📷
        </label>
...

下一步是value将输入文本字段的 设置为query并向其添加onChange()事件。onChange()事件将有一个函数,在该函数setQuery()中将用于更新状态。使用e.target.value以下方法检索输入字符串

反应照片搜索/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)在您定义状态的位置之后添加

反应照片搜索/src/searchPhotos.js
...
export default function SearchPhotos() {
   const [query, setQuery] = useState("");
   console.log(query);

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

保存文件。

您现在将在控制台内收到输入查询。您可以打开控制台,使用F12浏览器Ctrl+Shift+KFirefox中

浏览器控制台演示此应用程序的用户输入日志记录。

现在,searchPhotos.js看起来像这样:

反应照片搜索/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 Hooks,并将用户输入存储inputquery状态内的字段中在下一节中,您将使用此搜索查询来搜索图像并将响应存储在另一个状态中。

第 6 步 – 向 Unsplash 发出 API 请求

现在,您将使用unsplash-js库通过input字段中的查询来搜索图像响应将存储在另一个名为pics.

您已经安装了该unsplash-js库,因此将其导入到searchPhotos.js文件中。您还可以删除console.log()上一节中的语句:

反应照片搜索/src/searchPhotos.js
import React, { useState } from "react";
import Unsplash, { toJson } from "unsplash-js";

...

toJsonunsplash-js库中的一个辅助函数,用于将响应转换为JSON 格式您可以在unsplash-jsGitHub 页面了解有关辅助函数的更多信息

要在您的应用程序中使用 Unsplash,请使用如下new 关键字创建一个实例

反应照片搜索/src/searchPhotos.js
import React, { useState } from "react";
import Unsplash, { toJson } from "unsplash-js";

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

粘贴您的 UnsplashAccess Key进行替换your_Access_Key,您现在可以发出 API 请求。

警告:永远不要共享 API 或任何服务的任何访问密钥或客户端 ID。潜在的不良行为者可能会在互联网上滥用它们。在这种情况下,他们可能会发出异常数量的请求,这些请求可能会被您的服务提供商标记为垃圾邮件,从而停用您的应用程序和帐户。

现在您将创建一个异步函数函数将在单击“搜索”按钮时触发

就在您为 定义状态的位置之后query,定义一个async函数:

反应照片搜索/src/searchPhotos.js
...
export default function SearchPhotos() {
  const [query, setQuery] = useState("");

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

e.preventDefault()每当单击搜索”按钮时,此处都会阻止页面重新加载您可以onSubmitform标签内的事件中传递此函数您可以在官方 React 文档中阅读更多相关信息

反应照片搜索/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()函数中:

反应照片搜索/src/searchPhotos.js
...
const searchPhotos = async (e) => {
  e.preventDefault();
  unsplash.search
    .photos(query)
    .then(toJson)
    .then((json) => {
      console.log(json);
    });
};
...

首先,您使用unsplash.search然后指定要搜索的内容,在本例中为photos我们也可以搜索userscollectionsphotos将第一个必需参数作为要搜索的关键字,即query; 您还可以通过可选参数指定页面、每页响应、图像方向等。对于本教程,您只需要pageper_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"
                },
    ...
}

console.log()当您发现来自 Unsplash API 的成功响应时,您可以删除或注释该语句,这意味着您的代码运行良好。此应用程序将使用该"urls"字段,因为它将是图像的来源。

您现在已经使用来自用户的查询在使用单击搜索”按钮时搜索图像unsplash-js接下来,您将响应存储在另一个名为的状态中,pics并通过映射此状态中的元素来显示图像。

步骤 7 — 在网页上显示图像

在最后一部分中,您将把来自 Unsplash API 的响应存储在另一个名为的状态中pics,然后映射该状态的元素以在网页上显示图像。

要显示图像,您需要访问响应 JSON,为此,将需要另一个状态。之前的状态query存储了来自用户的查询,用于向 Unsplash API 发出请求。此状态pics将存储您从 Unsplash API 获得的图像响应。

searchPhotos.js像这样定义另一个状态:

反应照片搜索/src/searchPhotos.js
...
  const [query, setQuery] = useState("");
  const [pics, setPics] = useState([]);
...

此状态已用空数组初始化,所有响应都将作为对象存储在此状态内。换句话说,这是一个对象数组。

要使用 JSON 更新此状态,您将使用setPics内部unsplashAPI 请求:

反应照片搜索/src/searchPhotos.js
...
    unsplash.search
      .photos(query, 1, 20)
      .then(toJson)
      .then((json) => {
        setPics(json.results);
  });
...

现在,每次搜索新查询时,此状态都会相应更新。

接下来,创建一个divclassName="card-list"流向何方后form标签结束:

反应照片搜索/src/searchPhotos.js
...
        <button type="submit" className="button">
          Search
        </button>
      </form>
      <div className="card-list">
      </div>
    </>
  );
}

在 this 中div,您将映射状态并显示id图像:

反应照片搜索/src/searchPhotos.js
...
        <button type="submit" className="button">
          Search
        </button>
      </form>
      <div className="card-list">
        {pics.map((pic) => pic.id )}
      </div>
    </>
  );
}

您首先使用{}传递 JavaScript 表达式,在其中使用状态上.map()方法

保存您的文件。如果你现在搜索,你会看到ids 与网页上的不同对象相关联:

在网页上呈现重叠 ID 结果的应用程序

这很混乱,但这也意味着您的应用程序正在运行。

不是显示pic.id而是map函数内部打开 JSXdiv使用className="card". 这将是每个单独图像的容器:

反应照片搜索/src/searchPhotos.js
...
        <button type="submit" className="button">
          Search
        </button>
      </form>
      <div className="card-list">
        {
          pics.map((pic) => <div className="card"></div>);
        }
      </div>
    </>
  );
}

您现在可以在其中显示图像div

反应照片搜索/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的alt描述。

里面有不同的字段"urls"提供不同的数据,例如:

raw:用户拍摄的实际原始图像。
full.jpg格式的原始图像
regular:最适合实际用途,width=1080px
small: 非常适合慢速网速,width=400px.
thumb:图像的缩略图版本,width=200px

在本教程中,您使用的是full,但您也可以尝试其他类型。您还为图像提供了默认值heightwidth

保存您的文件。

您的申请即将完成;如果您现在搜索,您将能够看到您的应用程序正在运行。但是还剩下一小行代码。如果您在浏览器中搜索您的图像并转到您的控制台,您将看到一条警告。

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

To fix this, pass a unique key to every child using the id of the image. This key prop explicitly tells React the identity of each child in a list; this also prevents children from losing state between renders:

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

You can adjust the number of images you want to show by passing the corresponding argument to unsplash.search.photos().

Save and exit the file. You’ll now have a working photo search app:

在应用程序中搜索“apple”一词并获取苹果图像结果的动画

In this section, you stored the response from Unsplash API inside the pics state and displayed the images by mapping over the elements in pics.

Conclusion

In this tutorial, you developed a React Photo Search app with the Unsplash API. In building the project, the tutorial discussed how to use React Hooks, query an API, and style a user interface.

这个应用程序可以做很多事情来扩展它。例如,您可以添加一个随机按钮来显示随机图像,创建一个复选框以根据用户的偏好在搜索照片或发布照片的用户之间切换,添加无限滚动以显示更多图像等等。您还可以使用相同的概念并制作其他涉及 API 请求的项目,例如Hacker News API

如果您想查看更多 React 教程,请查看我们的React 主题页面

觉得文章有用?

点个广告表达一下你的爱意吧 !😁