ساخت برنامه جستجوی تصویر در React با استفاده از Unsplash API

?How to Make an Image Search App in React using the Unsplash API

21 اردیبهشت 1401
Image-Search-App-in-React

Unsplash سایتی است که می توانید تصاویر رایگان را دانلود کرده و به دلخواه از آن ها استفاده کنید. در این آموزش، ما با استفاده از Unsplash API یک برنامه جستجوی تصویر می سازیم تا به تصاویر آن دسترسی داشته باشیم و هم چنین آن ها را دانلود کنیم.

پیش از شروع بیایید ببینیم برنامه از چه بخش هایی تشکیل شده است:

  1. نحوه ساخت یک برنامه React
  2. پاک سازی برنامه
  3. چگونه رابط کاربری برنامه خود را بسازیم
  4. نحوه دریافت کلید دسترسی و API Endpoint از Unsplash
  5. نحوه استفاده از Hooks در برنامه
  6. نحوه نمایش تصاویر در برنامه
  7. نحوه رسیدگی به خطاها
  8. نتیجه

چه چیزی یاد خواهیم گرفت؟

این پروژه برای مبتدیان است، اما هر کسی که می‌خواهد مهارت‌های خود را تقویت کند، می‌تواند آن را بخواند. در این آموزش موضوع های زیر را یاد خواهید گرفت:

  • نحوه دریافت API Endpoint و کلیدهای دسترسی از داشبورد برنامه‌نویسی Unsplash
  • نحوه استفاده از هوک های useState و useEffect برای واکشی داده ها
  • نحوه استفاده از تابع map برای نمایش تصاویر یا هر داده دیگری

نحوه ساخت یک برنامه React

ایجاد یک برنامه React بسیار آسان است. فقط کافی است به دایرکتوری مورد نظر خود بروید و دستور زیر را در ترمینال وارد کنید:

npx create-react-app image-search-app
دستور ساخت یک برنامه React

اگر مطمئن نیستید که چگونه می توانید یک پروژه React را به درستی ایجاد و راه اندازی کنید، می توانید به راهنمای رسمی در این نشانی مراجعه کنید.‌‌‌

پس از نصب برنامه، npm start را در همان ترمینال اجرا کنید تا localhost:3000 که در آن برنامه React ما میزبانی می شود، راه اندازی شود. ما هم چنین می توانیم تمام تغییرات خود را در آن جا مشاهده کنیم.

پاک سازی برنامه

در ادامه نیاز داریم که برنامه خود را پاک سازی کنیم. منظور این است که باید فایل ها و کدهایی را که نیاز نداریم را پاک کنیم. در پوشه src به بعضی از فایل ها نیاز نداریم. این پوشه پیش از پاک سازی به شکل زیر است:

پوشه src پیش از پاک سازی

پوشه src پس از پاک سازی باید به شکل زیر درآید:

پوشه src پس از پاک سازی

سپس باید فایل های موجود در تصویر بالا را به خاطر تغییرهای پیش آمده ویرایش کنیم. کد زیر را در فایل App.js قرار می دهیم:

import React from "react";
const App = () => {
  return (
    <>
      <div className="container-fluid mt-4">
        <div className="row">
          <div className="col-12 d-flex justify-content-center align-items-center input">
            <input
              className="col-3 form-control-sm py-1 fs-4 text-capitalize border border-3 border-dark"
              type="text"
              placeholder="Search Anything..."
            />
            <button
              type="submit"
              // onClick={Submit}
              className="btn bg-dark text-white fs-3 mx-3"
            >
              Search
            </button>
          </div>
        </div>
      </div>
    </>
  );
};
export default App;

در ادامه فایل index.css را کاملا پاک می کنیم.برای استایل دهی برنامه از bootstrap استفاده می کنیم.برای استفاده از bootstrap کد زیر را در index.html در پوشه public قرار می دهیم.

پوشه public
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>Image Search Application</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
  </body>
</html>

سپس تغییرهای زیر را در فایل index.js به وجود می آوریم:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { createRoot } from 'react-dom/client';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App  />);

چگونه رابط کاربری برنامه خود را بسازیم؟

دو بخش در رابط کاربری برنامه ما وجود دارد:

  1. بخش ورودی یا Input
  2. بخش Result که در آن تصاویر را نشان خواهیم داد

در قسمت Input یک تگ input داریم که عبارت یا query جستجو را در آن می نویسیم. ما هم چنین یک دکمه با یک کنترل کننده رویداد onClick داریم که عملکرد مسئول واکشی داده ها از API را اجرا می کند.

برنامه را با دستور npm start اجرا می کنیم.تا این جا تصویر برنامه به صورت زیر خواهد بود:

در این مقاله در مورد استایل برنامه صحبت نمی کنیم. به این ترتیب می‌توانیم روی بخش React که درک آن ضروری‌تر است، تمرکز بیشتری داشته باشیم.

نحوه دریافت کلید دسترسی و API Endpoint از Unsplash

بیایید کلیدهای API را از Unsplash for Developer دریافت کنیم. برای دریافت کلید API و سایر جزئیات مراحل زیر را دنبال کنید.ابتدا به این لینک بالا بروید و روی ثبت نام به عنوان توسعه دهنده کلیک کنید.

سپس input های که خواسته شده را پر کنید.

پس از این کار، شما به داشبورد developer (توسعه دهنده) هدایت می شوید. روی New Application کلیک کنید.

از شما خواسته می شود که تمام شرایط نوشته شده در آن جا را بپذیرید. پس هم آن ها را کلیک کنید. سپس برای ادامه روی دکمه Accept terms کلیک کنید.

در مرحله بعد، یک فرم modal مانند شکل زیر ظاهر می شود که در آن باید اطلاعات برنامه مانند نام و توضیحات را بنویسید. سپس روی Create Application کلیک کنید.

اکنون که برنامه ما ایجاد شده است، می‌توانیم به کلید دسترسی و کلید مخفی در بخش Keys دسترسی داشته باشیم:

توجه کنید که کلمه Demo در همان ابتدای این صفحه، به ایت معنی است که درخواست ما پذیرفته شده است اما هنوز در حالت توسعه است.در این حالت فقط می توانیم 50 درخواست در ساعت داشته باشیم. اگر از این حد تجاوز کنیم، API ما کار نمی کند و تصاویر بارگیری نمی شوند.

پس از این، به documentation بروید و گزینه "Search Photos by Keyword" را انتخاب کنید.

به بخش Response در پایین بروید و پیوند را مانند تصویر کپی کنید:

حالا هم کلید API خود را داریم و هم API Endpoint  بیایید ساخت برنامه خود را ادامه دهیم.

نحوه استفاده از Hooks در برنامه

ما از هوک های useState و useEffect در برنامه خود استفاده خواهیم کرد. آن‌ها به ما اجازه می‌دهند state هایی را که برای دریافت مقدار ورودی لازم است تنظیم کنیم و داده‌های مربوط به آن مقدار را در API جستجو کنیم. برای این که هوک ها کار کنند، باید آن ها را در بالای برنامه خود در فایل App.js به این صورت تعریف کنیم:

import React, { useState, useEffect } from "react";

نحوه مقداردهی state با استفاده از هوک  useState

همان طور که در بالا توضیح دادیم، از هوک ها برای استخراج داده ها از API با استفاده از مقدار وارد شده در قسمت input استفاده می کنیم. این مقدار توسط برنامه با استفاده از هوک useState خوانده می شود.

state ها را با استفاده از این هوک برای اهداف خاص تعریف می کنیم. در این برنامه، دو مورد از آن ها را تعریف خواهیم کرد: یکی برای دریافت مقدار از فیلد input و دیگری برای نمایش نتایج واکشی شده از API.

const [img, setImg] = useState("");

const [res, setRes] = useState([]);

دو پارامتر در کد بالا وجود دارد که برای تعریف هوک useState استفاده می شود: یکی از آن ها حالتی است که از آن برای ذخیره مقادیر استفاده می کنیم و دیگری تابعی است که برای به روز رسانی مقادیر state استفاده خواهیم کرد. اطلاعات بیشتر در مورد هوک useState را این جا بخوانید.

state اول را به عنوان یک رشته خالی تعریف کرده ایم زیرا از آن برای ذخیره ورودی از نوار جستجو استفاده می شود.

state دیگر به عنوان یک آرایه خالی مقدار دهی اولیه می شود زیرا داده های واکشی شده از API را ذخیره می کند و سپس آن را در بخش نتیجه ما نشان می دهد.

به‌طور پیش‌فرض، فقط می‌توانیم تا 10 داده در هر درخواست دریافت کنیم، اما می‌توانیم با استفاده از پارامتر per_page که بعدا در این آموزش مشاهده خواهیم کرد، از آن فراتر برویم.

نحوه استفاده از state برای img

مرحله بعدی ذخیره مقدار فیلد متن ورودی در state برای img با استفاده از ویژگی value تگ input است. سپس یک کنترل کننده رویداد onChange به آن اضافه می کنیم. این کنترل کننده رویداد onChange() تابعی خواهد داشت که برای به روز رسانی حالت با استفاده از e.target.value استفاده می شود.

<input
  className="col-3 form-control-sm py-1 fs-4 text-capitalize border border-3 border-dark"
  type="text"
  placeholder="Search Anything..."
  value={img}
  onChange={(e) => setImg(e.target.value)}
/>;

نحوه ایجاد درخواست های API از Unsplash با استفاده از هوک useEffect

اکنون از Unsplash API و کلید دسترسی که در مرحله بالا به دست آورده ایم برای واکشی داده ها و نمایش آن ها در برنامه خود استفاده می کنیم.

برای این کار، دوباره به یک state برای ذخیره داده‌های واکشی شده از API که قبلا در بخش بالا تعریف کرده‌ایم نیاز داریم (res برای این منظور به عنوان یک آرایه خالی مقدار دهی اولیه می‌شود).

روش‌های زیادی در جاوا اسکریپت وجود دارد که می‌توانیم از آن ها برای واکشی داده‌ها از یک API استفاده کنیم، اما از روش async-wait استفاده می‌کنیم. این بسیار ساده‌ترین روش است.

const fetchRequest = async () => {
  const data = await fetch(
    `https://api.unsplash.com/search/photos?page=1&query=${img}&client_id=${Access_Key}`
  );
  const dataJ = await data.json();
  const result = dataJ.results;
  console.log(result);
  setRes(result);
};
useEffect(() => {
  fetchRequest();
}, []);

توجه داشته باشید که ${Access_Key} را نوشته ایم .در این جا باید کلید دسترسی خود را بنویسیم. این مرحله را تکمیل می کنیم تا کلید API خود را ایمن کنیم زیرا هر کسی می تواند از آن سو استفاده کند.

در Unsplash نیز می‌توانیم برای تولید اپلیکیشن خود اقدام کنیم و با این کار می‌توانیم با تصاویری که Unsplash ارائه می‌کند آنلاین شویم.

به همین دلیل، همه افراد مجموعه متفاوتی از کلیدهای دسترسی و کلیدهای امنیتی را دریافت می کنند. همیشه بهتر است این کلیدها را از دیگران پنهان کنید تا مورد سو استفاده قرار نگیرد و ما بهای آن را بپردازیم.

در کد بالا، ابتدا داده‌های واکشی شده از API را در متغیر data ذخیره کرده‌ایم که سپس برای سادگی به JSON تبدیل می‌شود. این به ما امکان می‌دهد داده‌ها را بخوانیم و مقادیر لازم را استخراج کنیم، که در متغیر dataJ ذخیره می‌شوند و برای بررسی این که آیا مقدار مورد نیاز خود را دریافت می‌کنیم یا خیر، کنترل می‌شوند.

API در فرمت JSON

و اگر یکی از نتایج جستجوی بالا را باز کنیم تا ببینیم چه مقادیری برای استخراج وجود دارد:

{
    "total": 133,
    "total_pages": 7,
    "results": [
    {
    "id": "eOLpJytrbsQ",
    "created_at": "2014-11-18T14:35:36-05:00",
    width: 4000,
    height: 3000,
    color: "#A7A2A1",
    blur_hash: "LaLXMa9Fx[D%~q%MtQM|kDRjtRIU",
    likes: 286,
    liked_by_user: false,
    description: "A man drinking a coffee.",
    user: {
    id: "Ul0QVz12Goo",
    username: "ugmonk",
    name: "Jeff Sheldon",
    first_name: "Jeff",
    last_name: "Sheldon",
    instagram_username: "instantgrammer",
    twitter_username: "ugmonk",
    portfolio_url: "http://ugmonk.com/",
    profile_image: {
    small:
    "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32&s=7cfe3b93750cb0c93e2f7caec08b5a41",
    medium:
    "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64&s=5a9dc749c43ce5bd60870b129a40902f",
    large:
    "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128&s=32085a077889586df88bfbe406692202",
    },
    links: {
    self: "https://api.unsplash.com/users/ugmonk",
    html: "http://unsplash.com/@ugmonk",
    photos: "https://api.unsplash.com/users/ugmonk/photos",
    likes: "https://api.unsplash.com/users/ugmonk/likes",
    },
    },
    current_user_collections: [],
    urls: {
    raw: "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f",
    full: "https://hd.unsplash.com/photo-1416339306562-f3d12fefd36f",
    regular:
    "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=92f3e02f63678acc8416d044e189f515",
    small:
    "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&s=263af33585f9d32af39d165b000845eb",
    thumb:
    "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=8aae34cf35df31a592f0bef16e6342ef",
    },
    links: {
    self: "https://api.unsplash.com/photos/eOLpJytrbsQ",
    html: "http://unsplash.com/photos/eOLpJytrbsQ",
    download: "http://unsplash.com/photos/eOLpJytrbsQ/download",
    },
    },
    // more photos ...
    ],
    },

بهتر است از این تابع در داخل هوک useEffect استفاده کنید، زیرا در صورت ایجاد هر گونه تغییر در رابط کاربری برنامه، از رندر مجدد داده ها جلوگیری می کند. برای درک عمیق useEffect، این جا را کلیک کنید.

ما از تابع setRes برای به روز رسانی مقدار res که یک آرایه خالی است و درنهای  به آرایه ای تبدیل می شود که همه داده های واکشی شده را در فرمت JSON ذخیره می کند، استفاده می کنیم.

قبلا یک تابع onClick را به دکمه در ابتدای برنامه خود در بخش ورودی داده ایم. اکنون زمان آن است که یک تابع برای این کنترل کننده رویداد تعریف کنیم که به محض کلیک روی دکمه جستجو فعال می شود. نام این تابع fetchRequest است که داده ها را واکشی می کند و نتیجه را در قسمت Result به ما نشان می دهد.

const Submit = () => {
  fetchRequest();
  setImg("");
};

نحوه نمایش تصاویر در برنامه

در بخش بالا، داده‌های واکشی شده از API در یک آرایه ذخیره شده. برای به دست آوردن و نمایش این مقادیر، باید از متد map استفاده کنیم.

<div className="col-12 d-flex justify-content-evenly flex-wrap">
  {res.map((val) => {
    return (
      <>
        <img
          className="col-3 img-fluid img-thumbnail"
          src={val.urls.small}
          alt="val.alt_description"
        />
      </>
    );
  })}
</div>;

اگر به عقب برگردیم و پاسخ را به شکل JSON ببینیم، نوع دیگری از اطلاعات را خواهیم یافت: URL هایی که حاوی path تصویر هستند. بنابراین در این جا val.urls.small مسیر واقعی تصویر است و val.alt_description توضیحات alt تصویر است.فیلدهای مختلفی در داخل "url" وجود دارد که داده های متفاوتی را نشان می دهد، مانند:

  • Raw: تصویر خام واقعی که توسط یک کاربر گرفته شده است.
  • Full: تصویر خام با فرمت jpg
  • Regular: بهترین برای استفاده های عملی، width=1080px.
  • Small: مناسب برای سرعت پایین اینترنت، width=400px.
  • Thumb: نسخه بندانگشتی تصویر، width=200px.

در این مقاله، ما از Small استفاده خواهیم کرد، اما موارد دیگری نیز وجود دارد که در بالا نشان داده شده است که می‌توانیم با آن ها کار کنیم و مورد مناسب خود را پیدا کنیم.

به‌طور پیش‌فرض، تعداد آیتم هایی که می‌توان در یک زمان واکشی کرد 10 آیتم است، اما این تعداد بسته به تعداد تصویری که می‌خواهیم برنامه‌مان نشان دهد، می‌تواند افزایش یا کاهش یابد.

برای انجام این کار فقط باید یک پارامتر در پایان فراخوانی API خود (per_page) همان طور که در کد نشان داده شده است اضافه کنیم و آن را برابر با تعداد تصاویری که می خواهیم نشان دهیم قرار دهیم.

const fetchRequest = async () => {
  const data = await fetch(
    `https://api.unsplash.com/search/photos?page=1&query=${img}&client_id=${Access_Key}&per_page=20`
  );
  const dataJ = await data.json();
  const result = dataJ.results;
  console.log(result);
  setRes(result);
};

پارامترهای بسیار بیشتری وجود دارد که Unsplash ارائه می دهد.

پارامترهای Unsplash API

کد کامل فایل App.js تا این جا به شکل زیر است:

import React, { useState, useEffect } from "react";

const App = () => {
  const [img, setImg] = useState("");
  const [res, setRes] = useState([]);

  const fetchRequest = async () => {
    const data = await fetch(
      `https://api.unsplash.com/search/photos?page=1&query=${img}&client_id=${'P60hRbAd1LyTJpknpt4FwTfKQp8uH-8dJM3DIOTX3is'}`
    );
    const dataJ = await data.json();
    const result = dataJ.results;
    console.log(result);
    setRes(result);
  };

  useEffect(() => {
    fetchRequest();
  }, []);
  
  const Submit = () => {
    fetchRequest();
    setImg("");
  };
  

  return (
    <>
      <div className="container-fluid mt-4">
        <div className="row">
          <div className="col-12 d-flex justify-content-center align-items-center input">
          <input
            className="col-3 form-control-sm py-1 fs-4 text-capitalize border border-3 border-dark"
            type="text"
            placeholder="Search Anything..."
            value={img}
            onChange={(e) => setImg(e.target.value)}
          />

            <button
              type="submit"
              onClick={Submit}
              className="btn bg-dark text-white fs-3 mx-3"
            >
              Search
            </button>
          </div>
        </div>

        <div className="col-12 mt-4 d-flex justify-content-evenly flex-wrap">
        {res.map((val) => {
          return (
            <>
              <img
                className="col-3 img-fluid img-thumbnail"
                src={val.urls.small}
                alt="val.alt_description"
              />
            </>
          );
        })}
      </div>

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

نحوه رسیدگی به خطاها

اگر اکنون در مورد فلگ ها جستجوی سریع انجام دهیم، تصاویر خود را دریافت خواهیم کرد. اما هنوز برخی از مشکلات وجود دارد که باید برطرف شود. یکی از آن ها خطایی است که در کنسول دریافت می کنیم.

خطا در console

برای رفع این مشکل، یک کلید منحصر به فرد را با استفاده از شناسه تصویر به هر فرزند ارسال کنید. این کلید prop به صراحت هویت هر فرزند را در یک لیست به React می گوید. این کلید همچنین از نابودی state فرزندان  بین رندرها جلوگیری می کند.

<div className="col-12 d-flex justify-content-evenly flex-wrap">
  {res.map((val) => {
    return (
      <>
        <img
          key={val.id}
          className="col-3 img-fluid img-thumbnail"
          src={val.urls.small}
          alt="val.alt_description"
        />
      </>
    );
  })}
</div>;

اگر برنامه  را باز کنیم و در input به عنوان مثال کلمه cat را بنویسیم با تصویر زیر روبه رو خواهیم شد:

کد کامل این برنامه را می توانید از این نشانی دانلود کنید.

نتیجه

در این آموزش، ما یک برنامه جستجوی عکس در React با استفاده از Unsplash API ایجاد کرده ایم. در حین ساختن برنامه، موارد زیادی مانند نحوه استفاده از هوک های React برای دریافت داده‌ها از یک API و استفاده از آن برای نمایش تصاویر در برنامه خود بحث کردیم.

کارهای بیشتری وجود دارد که می توانید در  این برنامه انجام دهید. به عنوان مثال، می‌توانیم یک دکمه تصادفی برای نمایش تصاویر تصادفی اضافه کنیم، یک چک باکس برای جابه‌جایی بین جستجوی عکس‌ها یا کاربرانی که آن‌ها را بر اساس ترجیح کاربر ارسال کرده‌اند ایجاد کنیم، یک اسکرول بی‌نهایت برای نمایش تصاویر بیشتر اضافه کنیم و موارد دیگر.


منبع: وب سایت freecodecamp

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.