В этой статье будет продемонстрировано, как реализовать функцию поиска по полученному набору данных. Эта функция позволит нам искать все символы, доступные через API. Примечание. Эта статья является продолжением статьи Извлечение данных с помощью apollo-client в React из GraphQL API.
Что мы строим.
Поведение, которого мы хотим добиться, заключается в том, что когда пользователь вводит имя персонажа в поле поиска и нажимает кнопку «Отправить», этот символ отображается на веб-странице.
Инициализировать состояние
Поведение, которое мы хотим реализовать, заключается в том, что если элемент ввода пуст, он должен отображать все символы. Если в строке поиска есть текст, в ней должны отображаться только символы, включающие эту текстовую строку.
Теперь давайте объявим переменную состояния для хранения поискового запроса — символов, которые мы ищем. В компоненте App
вызовите useState()
, чтобы объявить переменную состояния с именем searchInput
и функцию обновления состояния с именем setSearchInput
. установитьSearchQuery. Передайте значение useState()
a в качестве начального состояния запроса:
const [searchInput, setSearchInput] = useState("");
Здесь значение, с которого мы хотим начать, представляет собой пустую строку. Состояние searchInput
будет обновлено значением, которое пользователь вводит в поле ввода поиска.
В компоненте App
создайте функцию с именем handleSearch
, которая обновляет состояние searchInput
, когда пользователь отправляет значение. Событие, которое функцияhandleSearch
получает в качестве параметра, представляет собой объект, содержащий поле target
. Это target
— это элемент DOM, к которому привязан обработчик событий (т. е. поле ввода текста). Получив доступ к этому полю, мы можем определить, на что будет изменено значение target
:
const handleSearch = e => { const searchQuery = e.target.value && e.target.value.toLowerCase(); console.log(searchQuery) setSearchInput(searchQuery) };
Теперь нам нужно подключить функцию handleSearch
к компоненту SearchBar
. В файле App.js
импортируйте и вставьте компонент SearchBar
непосредственно внутри элемента .container
:
import SearchBar from './SearchBar' return ( <div className="container"> <SearchBar /> </div> )
Дайте компоненту SearchBar
свойство handleSearch
, передав ему ссылку на функцию handleSearch
и свойство searchInput
, передав ему ссылку на значение searchInput
:
const App = () => { const [searchInput, setSearchInput] = useState(""); const handleSearch = e => { const searchQuery = e.target.value && e.target.value.toLowerCase(); console.log(searchQuery) setSearchQuery(searchQuery) }; return ( <div className="container"> <SearchBar searchInput={searchInput} handleSearch={handleSearch} /> </div> ); }
Логика поиска
Мы используем перехватчик useEffect()
для определения логики, которая возвращает список символов для результатов поиска после рендеринга компонента. Напомним, хук useEffect()
принимает два аргумента: функцию и массив зависимостей.
Переменная searchResults
фильтрует список символов, затем принимает имя символа и преобразует его в нижний регистр с помощью метода toLowerCase
. Затем использует метод includes
, чтобы определить, содержит ли имя персонажа searchQuery
.
useEffect(() => { const searchResults = data?.characters?.results.filter(character => character.name.toLowerCase().includes(searchQuery)) setSearchedCharacters(searchResults) }, [searchQuery, data])
Наконец, если зависимость не указана, эффект запускается после каждого рендеринга. Если он пуст, то он запустится один раз. Однако он должен содержать список значений, используемых в эффекте. Эффект запускается после изменения любого из этих значений. В данном случае мы передаем searchQuery
, поскольку он меняется при каждом поиске пользователя, и data
, поскольку он возвращает разные результаты метода фильтра.
Создать компонент панели поиска
Теперь мы фактически создадим компонент SearchBar
, который мы ранее поместили в компонент App
:
$ touch src/SearchBar.js
В файл SearchBar.js
импортируйте хук useState
:
import { useState } from 'react';
Создайте функциональный компонент и скопируйте фрагмент кода для Bootstrap NavBar — удалите элементы form
и button
:
const SearchBar = () => { return( <nav class="navbar navbar-expand-lg bg-body-tertiary"> <div class="container-fluid"> <a class="navbar-brand" href="https://rickandmortyapi.com/documentation/">Rick and Morty</a> <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"> </div> </nav> ) } export default SearchBar;
Передайте параметры searchInput
и handleSearch
в функцию SearchBar
. Обратите внимание: мы извлекли значения из объекта props (то есть деструктуризации), что дает нам возможность использовать props
без необходимости повторять это слово по всему коду. Напомним, они были добавлены в качестве реквизита к компоненту SearchBar
в файле App.js
.
const SearchBar = ({searchInput, handleSearch}) => { return( <nav class="navbar navbar-expand-lg bg-body-tertiary"> <div class="container-fluid"> <a class="navbar-brand" href="https://rickandmortyapi.com/documentation/">Rick and Morty</a> <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"> </div> </nav> ) } export default SearchBar;
Теперь searchInput
и handleSearch
доступны в качестве реквизитов для передачи элементу ввода. Используйте обработчик onChange
для прослушивания любых изменений ввода и запуска события при изменении значения ввода.
Значением свойства является функция handleChange
, обработчик событий, определенный ранее в статье.
const SearchBar = ({searchInput, handleSearch}) => { return( <nav class="navbar navbar-expand-lg bg-body-tertiary"> <div class="container-fluid"> <a class="navbar-brand" href="https://rickandmortyapi.com/documentation/">Rick and Morty</a> <input class="form-control me-2" defaultValue={searchInput} onChange={handleChange} type="search" placeholder="Search characters" aria-label="Search"> </div> </nav> ) } export default SearchBar;
CSS-стиль
Давайте добавим те же цвета и шрифты, что и в предыдущих статьях. В дополнение к стандартным цветам темы Bootstrap давайте добавим собственные зеленый и черный. Давайте применим эти цвета к body
веб-страницы и border
каждой карточки персонажа.
@import "../node_modules/bootstrap/scss/bootstrap.scss"; $neonGreen: #C3ED3F; $softBlack: #141414; body { background-color: $neonGreen; } .card { box-shadow: 5px 5px 1px 1px $softBlack; border: 2px solid $softBlack; border-radius: 8px; }
Чтобы подчеркнуть бруталистский стиль веб-страницы, давайте используем для текста шрифт Google под названием Darker Grotesque. Выбранные семейства включают: Regular 400, Medium 500 и Bold 700.
Чтобы встроить выбранный шрифт, щелкните переключатель «Импорт» в правом столбце веб-страницы Darker Grotesque и вставьте ссылку на импорт в верхнюю часть файла custom.scss
. Затем скопируйте правило CSS для font-family
и вставьте его в селектор тела.
@import url('https://fonts.googleapis.com/css2?family=Darker+Grotesque:wght@400;500;700&display=swap'); @import "../node_modules/bootstrap/scss/bootstrap.scss"; $neonGreen: #C3ED3F; $softBlack: #141414; body { background-color: $neonGreen; font-family: 'Darker Grotesque', sans-serif; }
Заключение
В этой статье показано, как реализовать функцию поиска по полученному набору данных — API «Рик и Морти».