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

简介

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

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

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

照片搜索应用程序

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

先决条件

为了遵循本指南:

  • 您将需要一个免费的 Unsplash 帐户,您可以在官方 Unsplash 网站获得该帐户。

  • 你需要一个运行Node.js的开发环境;本教程在 Node.js 版本 10.20.1 和 npm 版本 6.14.4 上进行了测试。要在 macOS 或 Ubuntu 18.04 上安装它,请按照How to Install Node.js and Create a Local Development Environment on macOS或How To Install Node.js on 的 Installing Using a PPA 部分中的步骤操作Ubuntu 18.04。

  • 您还需要 JavaScript 和 HTML 的基本知识,您可以在我们的如何使用 HTML 系列和如何使用 JavaScript 编码中找到这些知识。 CSS 的基本知识也会很有用,您可以在Mozilla Developer Network找到。

第一步——创建一个空项目

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

npx create-react-app react-photo-search

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

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

cd react-photo-search

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

npm start

有关此启动脚本的信息,请查看How To Set Up a React Project with Create React App。

接下来,在 Web 浏览器中转到http://localhost:3000,或者如果您从远程服务器运行,则为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,那就从index.js中删除import './index.css';

一旦您从其中删除import ./index.css,您的index.js将与此类似。

反应照片搜索/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中删除所有内容,然后保存并退出文件。您将在 Step 3 中使用新样式对其进行更新。

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

nano src/App.js

下一步是删除import logo from './logo.svg';并从div中删除JSX和App.js文件中的className="App"。这将删除模板的 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 Developer Home并注册为开发人员。由于您已经创建了 Unsplash 帐户,这将是一个快速的过程。

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

Unsplash 开发者页面

填写您的凭据以进行注册。

注册为开发者后,您将被自动重定向到您的开发者仪表板。单击新应用程序

Unsplash Developer Dashboard with New Application

您将被要求接受API 使用和指南。单击复选框,然后单击 Accept terms 按钮以继续:

Unsplash API 使用和指南

然后系统会提示您提供您的申请信息。为您的应用程序提供适当的名称和描述,然后单击创建应用程序

Unsplash 应用信息弹窗

有了这个,您已经创建了一个应用程序,现在可以在 Keys 部分下访问您的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 社区存储库。

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

npm install unsplash-js

这是您按照本教程需要安装的唯一库;稍后,您可以尝试使用不同的 React 用户界面库,例如React-Bootstrap、Semantic 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") 有一些边距和填充,因此以下代码将所有四个边的marginpadding设置为0:

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

反应照片搜索/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可以设置为toprightbottomleft。如果只添加一个值,则该值将设置为所有toprightbottomleft。如果在margin中添加两个值,则第一个值将设置为topbottom,第二个将设置为rightleft

根据margin: 0 auto;,topbottom0边距,而leftrightauto。这个auto表示浏览器将根据容器设置边距。理解这一点的一个例子是,如果父元素是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对应于您的 App 的标题,即“React Photo Search”。只设置了两个属性,分别是font-sizefont-family。这里,rem的单位用于font-size的值。rem值是相对于根html元素的,不像em值是相对于父元素的。这里的4.4rem表示44px(4.4 x 10)。这个乘以10px是因为您使用*选择器将所有元素的字体大小设置为10pxfont-family指定元素的字体。代码中传递了许多值来充当_fallback_系统;如果浏览器不提供第一种字体,则设置下一种字体。

接下来是.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-sizepaddingbackground-colormargin-bottom,所以让我们讨论line-heightborder-radiusborder-radius定义了元素角的半径。这里的值设置为20px,它将用于所有四个边。将border-radius设置为50%可以使正方形元素变成椭圆形。line-height指定行的高度,设置为2.8rem28px

接下来是.buttonCSS 块,用于设置 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-radiusfont-sizeborder设置元素边框的样式、宽度和颜色。这里border用作border-widthborder-styleborder-color的简写属性。此代码在 Search 按钮周围添加了一个 1px 的纯黑色边框。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,它对应于divclassName="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 块。.card是指内部有图像的个体div,而.card--image是该图像的className:

反应照片搜索/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 开发人员网络上阅读有关它的更多信息。

最终的 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;
    }
}

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

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

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

这样就完成了应用程序的样式。保存并退出src/App.css。如果您想一起查看整个 CSS 文件,请查看此代码](https://github.com/do-community/react-photo-search/blob/master/src/App.css)的[GitHub 存储库。

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

第 4 步 — 设计用户界面

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

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

nano src/App.js

要为项目添加标题,请在App.js中创建一个divclassName="container"。在这个div中添加一个带有className="title"h1标签,并在标签内写入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>
  );
}

保存并退出文件。在您的浏览器中,您的应用现在将显示您的标题:

带有“React Photo Search”标题的应用程序

接下来,您将创建一个接收用户输入的表单。此表单将包含一个输入文本字段和一个提交按钮。

为此,创建一个新的组件命名为<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文件中的功能组件的基本结构。保存此文件。

下一步是在App.js中导入并使用SearchPhotos组件。

在新的终端窗口中,打开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>
    </>
  );
}

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

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

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

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

步骤 5 - 使用搜索查询设置状态

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

现在您已经构建了应用程序的基本结构,我们可以讨论 React 方面的事情。你有一个表单,但它还没有做任何事情,所以要做的第一件事就是从搜索栏中获取输入并访问它。您可以对状态执行此操作。

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

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

首先要做的是在searchPhotos.js文件中导入useState

打开文件:

nano src/searchPhotos.js

修改searchPhotos.js文件的第一行如下:

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

import React, { useState } from "react";

export default function SearchPhotos() {
...

接下来,您将实现useState()。这是useState()Hook 的语法:

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

保存文件。

您现在将在控制台内收到输入查询。您可以使用F12inChrome或Ctrl+Shift+KinFirefox打开控制台:

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

现在,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,并将用户输入存储在query状态内的input字段中。在下一部分中,您将使用此搜索查询来搜索图像并将响应存储在另一个状态中。

第 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。潜在的不良行为者可能会在互联网上滥用它们。在这种情况下,他们可能会发出异常数量的请求,这些请求可能会被您的服务提供商标记为垃圾邮件,这可能会停用您的应用程序和帐户。

现在您将创建一个异步函数,该函数将在单击 Search 按钮时触发。

就在您为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()会在单击 Search 按钮时停止页面重新加载。您可以在form标记内的onSubmit事件中传递此函数。你可以在官方 React 文档中阅读更多相关信息。

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

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

保存文件。现在,如果您单击 Search 按钮,您将在控制台中收到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 ()

保存文件。现在打开您的控制台并单击 Search 按钮。你会发现这样的响应 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库单击 Search 按钮时,您已使用来自用户的查询来搜索图像。接下来,您将把响应存储在另一个名为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 更新此状态,您将在unsplashAPI 请求中使用setPics:

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

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

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

接下来,在form标签结束的地方创建一个divclassName="card-list":

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

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

在这个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()方法 在您的状态。

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

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

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

不要显示pic.id,而是在map函数中打开 JSX,并使用className="card"创建一个新的div。这将是每个单独图像的容器:

反应照片搜索/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=1080pxsmall:适合慢速网速,width=400pxthumb:图像的缩略图版本,width=200px

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

保存您的文件。

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

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

要解决此问题,请使用图像的id将唯一的key传递给每个孩子。这个keyprop明确告诉 React 列表中每个孩子的身份;这也可以防止孩子在渲染之间丢失状态:

反应照片搜索/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中的元素来显示图像。

结论

在本教程中,您使用 Unsplash API 开发了一个 React Photo Search 应用程序。在构建项目时,本教程讨论了如何使用 React Hooks、查询 API 和设置用户界面样式。

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

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

Logo

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐