Создавайте собственные хуки для поиска и фильтрации данных, извлечения данных из API и обработки пользовательского ввода.

В этом посте мы создадим приложение, используя настраиваемые хуки реакции. Попутно узнав, как мы можем использовать хуки, - это разные части нашего приложения. Мы будем обрабатывать вводимые пользователем данные, извлекать данные из API, а также искать и фильтровать данные. Все на крючках.

Прежде чем мы начнем. Давайте посмотрим, что мы будем строить.

Предпосылки

  • Установлен инструмент Create React App
  • Базовые знания React Hooks

Давайте начнем

Создайте приложение для реагирования с машинописным текстом с помощью инструмента create-react-app.

create-react-app --template=typescript languages-search-app

Замените код в App.css приведенным ниже кодом.

.main {
  margin-top: 1rem;
}
.uppercase {
  text-transform: uppercase;
}
.text-center {
  text-align: center;
}
.search-input {
  display: block;
  margin: auto;
  width: 300px;
  padding: 0.5rem;
  font-size: 0.75rem;
}

App.tsx код.

import React from "react";
import "./App.css";
const App: React.FC = () => {
  return (
    <div className="main">
      <h2 className="text-center uppercase">Programming Languages</h2>
    </div>
  );
};
export default App;

Хук для получения данных из API

Начнем с крючка для получения данных.

import Language from "../types/Language";
import { useState, useEffect } from "react";
const useLanguages = () => {
  const [languages, setLanguages] = useState<Language[]>([]);
  const endpoint = "https://api.npoint.io/33d57619ef599fc57a53";

  useEffect(() => {
    fetch(endpoint)
      .then((response) => response.json())
      .then((data) => setLanguages(data))
      .catch((error) => console.log({ error }));
  }, []);
  return languages;
};
export default useLanguages;

Этот крючок объясняет сам себя. Сначала мы создаем состояние для хранения массива Language. Где Language

export default interface Language {
  id: string;
  name: string;
}

Затем внутрь крючка useEffect. Мы используем функцию fetch для извлечения данных из API, преобразования их в JSON и сохранения в состоянии. Обратите внимание, мы передаем пустой массив в качестве второго аргумента ловушке useEffect. Что равно componentDidMount в компоненте класса.

Сохраните ловушку под src/hooks/languagesHook.ts и Language введите под src/types/Language.ts.

Давайте воспользуемся этим перехватчиком и отрендерим данные.

import React from "react";
import "./App.css";
import useLanguages from "./hooks/languagesHook";
const App: React.FC = () => {
  const languages = useLanguages();
  return (
    <div className="main">
      <h2 className="text-center uppercase">Programming Languages</h2>
      {languages.slice(0, 10).map((l) => (
        <p className="text-center" key={l.id}>{l.name}</p>
      ))}
    </div>
  );
};
export default App;

Список языков огромен. Так что я пока ограничиваю его до 10.

Хук для обработки пользовательского ввода

В компоненте класса, чтобы отслеживать вводимые пользователем данные. Мы должны обрабатывать onChange для каждого поля ввода и обновлять значение в state. Используя хуки, мы можем сделать это лучше. Мы можем абстрагироваться от кода для хранения входного значения и реализации onChange. Вот как это сделать.

import { useState, useCallback } from "react";
const useUserInput = (defaultValue: string = "") => {
  const [value, setValue] = useState(defaultValue);
  const onChange = useCallback((e) => setValue(e.target.value), []);

  return {value, onChange,};
};
export default useUserInput;

Мы используем хук useCallback, поэтому функция не воссоздается для каждого рендера. Давайте посмотрим, как использовать этот крючок.

import React from "react";
import "./App.css";
import useLanguages from "./hooks/languagesHook";
import useUserInput from "./hooks/userInputHook";
const App: React.FC = () => {
  const searchText = useUserInput("");
  const languages = useLanguages();
  return (
    <div className="main">
      <h2 className="text-center uppercase">Programming Languages</h2>
      <input placeholder="Search languages here..." 
        type="text" 
        className="search-input text-center" 
        {...searchText} />
      {languages.slice(0, 10).map((l) => (
        <p className="text-center" key={l.id}>{l.name}</p>
      ))}
    </div>
  );
};
export default App;

useUserInput hook возвращает value и onChange в объекте. Мы можем использовать синтаксис распространения объекта, чтобы передать эти реквизиты в input.

Теперь, когда пользовательский ввод изменяется, мы можем получить доступ к значению с помощью searchText.value. Это все хорошо, но как мы будем искать в списке языков программирования и фильтровать данные. Это подводит нас к следующему зацепу.

Крючок для поиска и фильтрации списка данных

Вот.

import { useMemo } from "react";
const useSearchable = <T>(data: T[], searchText: string, searchProps: (item: T) => string[]) => {
  return useMemo(() => {
    const regex = new RegExp(searchText, "i");
    return data.filter((item) =>
      searchProps(item).some((sp) => regex.test(sp))
    );
  }, [data, searchText, searchProps]);
};
export default useSearchable;

Посмотрим, что здесь происходит. Во-первых, у нас есть общий параметр T. Что позволяет нам передавать любой тип массива. Тогда у нас есть 3 аргумента функции. 1-й массив T для данных, 2-й searchText для проверки элемента массива на совпадение и searchProps как функция. Потому что мы не знаем, какие свойства объекта мы должны проверить, чтобы определить, соответствует ли объект поисковому запросу. Поэтому мы воспринимаем это как аргумент. Учитывая объект, верните массив строк для повторного тестирования searchText, чтобы определить, совпадает он или нет.

Двигаемся дальше. Мы используем хук useMemo, чтобы запоминать результат поиска, а не вычислять его при каждом повторном рендеринге. В useMemo мы создаем RegExp для searchText. И отфильтруйте данные с помощью функции searchProps.

Давайте воспользуемся этим.

import React from "react";
import "./App.css";
import useLanguages from "./hooks/languagesHook";
import useUserInput from "./hooks/userInputHook";
import useSearchable from "./hooks/searchableHook";
const App: React.FC = () => {
  const searchText = useUserInput("");
  const languages = useLanguages();
  const searchableLanguages = useSearchable(
    languages,
    searchText.value,
    (l) => [l.name]
  );
  return (
    <div className="main">
      <h2 className="text-center uppercase">Programming Languages</h2>
      <input placeholder="Search languages here..." 
        type="text" 
        className="search-input text-center" 
        {...searchText} />
      {searchableLanguages.slice(0, 10).map((l) => (
        <p className="text-center" key={l.id}>{l.name}</p>
      ))}
    </div>
  );
};
export default App;

Вот и все. Вы можете посмотреть демо-версию приложения здесь.



Оформить заказ на репозиторий git.



Надеюсь, вы узнали из этого что-то новое.

Спасибо за чтение.