Начиная
Приложение автозаполнения — это то, что позволяет вам легко искать продукты, просто вводя соответствующий текст к фактическим названиям продуктов. В нашем случае мы будем работать над приложением для поиска продуктов питания, которое легко позволит вам искать соответствующие продукты питания.
Я уже создал структуру и важные стили приложения, используя React и SASS, мы будем добавлять логику поиска и автозаполнения.
Я использовал интерфейс командной строки create-react-app для создания и управления проектом приложения.
Вы можете получить полный исходный код с Github.
Домашний компонент
Вы можете представить его как многостраничное приложение с домашней страницей, на которой есть компонент поиска для поиска различных продуктов.
Обратите внимание, что все стили SASS представлены в репозитории проекта Github, поэтому рассмотрите возможность их получения.
/* pages/home.jsx */
import React from "react";
import Search from "../components/search";
export default class HomePage extends React.Component {
render() {
return (
<div className="page">
<div className="page-container">
<div className="container">
<Search />
</div>
</div>
</div>
);
}
}
И обязательно визуализируйте компонент в App.jsx.
/* App.jsx */
import React from "react";
import logo from "./logo.svg";
import "./App.scss";
import HomePage from "./pages/home";
function App() {
return (
<div className="App">
<HomePage />
</div>
);
}
export default App;
В приложении create-реагировать на приложение Project App.jsx по умолчанию отображается в DOM на index.js.
Давайте добавим панель поиска в середину нашей домашней страницы.
Бар поиска еды
Я уже создал элегантный дизайн для панели поиска, поэтому рассмотрите возможность получения файлов стилей из репозитория Github.
Теперь создайте папку компонентов внутри src/ и создайте папку search/ для панели поиска.
Создайте index.jsx в качестве основной точки входа компонента поиска.
import React from "react";
import "./style.scss";
import Popup from "./popup";
export default class Search extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div className="search">
<div className="search-container">
<div className="title">Type Food Name</div>
<div className="content">
<input
type="text"
placeholder="Food"
/>
<Popup isOpen={true} items={[{name: "Lasagna"}, {name: "Noodles"}]} />
</div>
</div>
</div>
);
}
}
Здесь мы добавили простой компонент поиска, который отображает всплывающее окно внизу. Компонент поиска довольно прост, поскольку все, что он делает, — это визуализирует ввод текста с компонентом всплывающего окна в нижней части ввода поиска.
Компонент Popup будет отвечать за отображение раскрывающегося всплывающего окна (Popover), которое отображает результат поиска, в этом случае он будет отображать результат поиска с автозаполнением продуктов питания.
/* components/search/popup.jsx */
import React from "react";
export default class Popup extends React.Component {
constructor(props) {
super(props);
}
render() {
const { items, isOpen } = this.props;
//Do not show popup
if (!isOpen) return null;
return (
<div className="popup">
<div className="container">
<div className="content">
{items &&
items.map((item, idx) => {
return (
<div className="item" key={idx}>
{item.name}
</div>
);
})}
{!items && <div className="warning">Nothing Found!</div>}
</div>
<div className="footer">Type Keyword to search for food</div>
</div>
</div>
);
}
}
Компонент Popup принимает список элементов для отображения в раскрывающемся списке вместе с опорой isOpen, чтобы отображать всплывающее окно или нет (показать и скрыть).
Из компонента поиска мы предоставляем простые тестовые данные в виде списка элементов для отображения во всплывающем окне. Вы можете проверить это, сохранив и открыв URL-адрес своего сервера разработки в браузере.
Получить автозаполнение
Это зависит от того, что ваше приложение фактически достигает конечной точки и извлекает данные о продуктах питания, но в этом случае мы будем использовать простой файл food.json, который имитирует конечную точку API для предоставления нам данных о продуктах питания.
Вот как выглядит ответ API-интерфейса food.json.
{
"foods": [
{
"name": "Lasagna",
"price": "12$"
},
{
"name": "Noodles",
"price": "8$"
},
{
"name": "Chicken Tikka",
"price": "16$"
},
{
"name": "Soup",
"price": "6$"
}
]
}
Вы можете добавить более подробную информацию о еде, например, о ее типе и о том, доступна ли она в меню на сегодня или нет.
Обязательно инициализируйте состояние с правильными значениями.
constructor(props) {
super(props);
this.state = {
isPopupOpen: false,
foods: [],
errors: [],
isError: false,
foundFoods: []
};
}
Лучший сценарий для извлечения данных о еде и поиска их для автозаполнения — это сначала получить их, когда компонент поиска впервые монтируется в DOM, чтобы мы могли избежать многократного извлечения данных, когда пользователь взаимодействует с веб-страницей, что может вызвать React повторный рендеринг, и мы не хотим попадать в конечную точку нашего сервера несколько раз с необходимостью.
/*search/index.jsx*/
...
constructor(props) {
super(props);
this.state = {
foods: [],
};
}
//Async keyword for working with Promises.
async fetchData() {
//Use ES6 fetch function to get json
const foods = await fetch("/resources/food.json").catch(err => {
this.setError("Cannot Load Food Data from Server!");
});
//Set foods in the state
this.setState({ foods: (await foods.json()).foods });
}
//Fetch data when the component is firstly mounted
componentDidMount() {
//Fetch & hold data on the state
this.fetchData();
}
...
Теперь мы получили данные в состоянии во-первых, когда компонент монтируется в DOM. Давайте попробуем найти в массиве искомое ключевое слово пользователем.
searchFood(keyword) {
//Get foods array list
const { foods } = this.state;
//Make sure to safely Escape keyword since it is coming from user's input
keyword = RegExp.escape(keyword.toLowerCase());
/*We generate a Regular Expression from the input keyword.
The Regex allows for having at least one character matched from the actual food name.
This way we can add autocomplete functionality.
*/
const pattern = `[A-Za-z.\s]*${keyword}[A-Za-z.\s]*`;
//Generate a Regex instance from string pattern
const matchRegex = new RegExp(pattern);
//Filter found foods that matches the current Regex
const foundFoods = foods.filter(item =>
matchRegex.test(item.name.toLowerCase())
);
//Set found foods on the state.
this.setState({ foundFoods });
}
Осталось только запускать метод searchFood всякий раз, когда пользователь что-то вводит в строке поиска, поэтому нам нужно прослушивать событие onChanage на входе.
onInputChange(e) {
const keyword = e.target.value;
this.searchFood(keyword);
}
onInput(e) {
if (e.target.value !== "") this.showPopup();
else this.hidePopup();
}
showPopup() {
this.setState({ isPopupOpen: true });
}
hidePopup() {
this.setState({ isPopupOpen: false });
}
Метод onInput будет запущен, когда пользователь начнет вводить ввод, чтобы мы могли отобразить всплывающее окно, чтобы показать результат поиска, нам также нужно убедиться, что значение не является пустым.
И мы меняем состояние isPopupOpen двумя независимыми методами, чтобы показать или скрыть всплывающее окно поиска.
Наконец, нам нужно управлять ошибками, устанавливая и очищая их в состоянии, чтобы вы могли информировать пользователя о любых технических ошибках или проблемах, связанных с поиском.
setError(msg) {
this.setState(prevState => ({
errors: [...prevState.errors, msg],
isError: true
}));
}
clearAllErrors() {
this.setState({ errors: [], isError: false });
}
Обязательно правильно визуализируйте ошибки, чтобы сделать ошибки более удобными и информативными, если в процессе поиска возникнут какие-либо ошибки.
Наконец, просто передайте правильные значения состояния, чтобы отобразить всплывающее окно и правильно перехватить события ввода.
...
render() {
const { isPopupOpen, foundFoods } = this.state;
return (
<div className="search">
<div className="search-container">
<div className="title">Type Food Name</div>
<div className="content">
<input
type="text"
placeholder="Food"
onInput={this.onInput.bind(this)}
onChange={this.onInputChange.bind(this)}
/>
<Popup isOpen={isPopupOpen} items={foundFoods} />
</div>
</div>
</div>
);
}
...
Вы можете попробовать найти еду в файле food.json и посмотреть, работает ли автозаполнение идеально, рассмотрите возможность получения данных из конечной точки API для надежного поиска.