В этом сообщении блога показано, как создать компонент панели поиска с помощью Next.js и Tailwind CSS. Вы узнаете, как использовать перехватчики React, динамическую маршрутизацию и пользовательский интерфейс Tailwind.
Nextjs с панелью поиска CSS попутного ветра с svg-значком героев слева и справа.
export default function Home() {
return (
<div className="flex flex-col items-center justify-center min-h-screen">
<div className="flex items-center justify-center">
<div className="flex border-2 rounded">
<input
type="text"
className="px-4 py-2 w-80"
placeholder="Search..."
/>
<button className="flex items-center justify-center px-4 border-l">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-6 h-6 text-gray-600"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"
/>
</svg>
</button>
</div>
</div>
<div className="mt-12">
<div className="flex border-2 rounded">
<button className="flex items-center justify-center px-4 border-r">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-6 h-6 text-gray-600"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"
/>
</svg>
</button>
<input
type="text"
className="px-4 py-2 w-80"
placeholder="Search..."
/>
</div>
</div>
</div>
);
}
Nextjs с адаптивным поиском CSS попутного ветра с использованием перехватчика useState.
import { useState } from "react";
export default function Home() {
const [searchTerm, setSearchTerm] = useState("");
const handleSearch = (event) => {
setSearchTerm(event.target.value);
console.log(`Searching for ${searchTerm}`);
};
return (
<div className="container mx-auto mt-20">
<div className="flex flex-col items-center justify-center">
<div className="">
<input
type="text"
value={searchTerm}
onChange={handleSearch}
className="w-full h-10 px-4 pr-10 text-sm bg-white border border-gray-300 rounded-lg lg:w-80 focus:outline-none"
placeholder="Search term..."
/>
</div>
{searchTerm && (
<div className="mt-10 text-2xl">Search term: {searchTerm}</div>
)}
</div>
</div>
);
}
Nextjs с фиктивными данными поиска книг CSS попутного ветра с использованием перехватчика useState.
import { useState } from "react";
const books = [
{ id: 1, title: "Moby Dick", author: "Herman Melville" },
{ id: 2, title: "The Great Gatsby", author: "F. Scott Fitzgerald" },
{ id: 3, title: "To Kill a Mockingbird", author: "Harper Lee" },
];
export default function Home() {
const [searchTerm, setSearchTerm] = useState("");
const [searchResults, setSearchResults] = useState([]);
const handleSearch = (event) => {
setSearchTerm(event.target.value);
if (event.target.value !== "") {
const results = books.filter((book) =>
book.title.toLowerCase().includes(event.target.value.toLowerCase())
);
setSearchResults(results);
} else {
setSearchResults([]);
}
};
return (
<div className="flex flex-col items-center justify-center min-h-screen py-2">
<div className="w-full max-w-md">
<div className="flex mt-10 border-2 border-gray-300 rounded-lg">
<input
type="text"
value={searchTerm}
onChange={handleSearch}
className="w-full px-4 py-2 text-sm focus:outline-none"
placeholder="Search books..."
/>
<button className="flex items-center justify-center px-4 bg-gray-300">
<svg
className="w-6 h-6 text-gray-500"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</button>
</div>
</div>
{searchResults.map((book) => (
<div key={book.id} className="mt-10 text-xl">
Title: {book.title}, Author: {book.author}
</div>
))}
</div>
);
}
Nextjs с помощью Tailwind CSS ищет поддельные данные API, используя useState и крючок useEffect.
import { useState, useEffect } from "react";
export default function Home() {
const [searchTerm, setSearchTerm] = useState("");
const [posts, setPosts] = useState([]);
const [filteredPosts, setFilteredPosts] = useState([]);
useEffect(() => {
const fetchPosts = async () => {
const response = await fetch(
"https://jsonplaceholder.typicode.com/posts"
);
const data = await response.json();
setPosts(data);
};
fetchPosts();
}, []);
useEffect(() => {
if (searchTerm !== "") {
const results = posts.filter((post) =>
post.title.toLowerCase().includes(searchTerm.toLowerCase())
);
setFilteredPosts(results);
} else {
setFilteredPosts([]);
}
}, [searchTerm, posts]);
const handleSearch = (event) => {
setSearchTerm(event.target.value);
};
return (
<div className="flex flex-col items-center justify-center min-h-screen py-2">
<div className="w-full max-w-md">
<div className="flex mt-10 rounded-lg">
<input
type="text"
value={searchTerm}
onChange={handleSearch}
className="w-full px-4 py-2 text-sm focus:outline-none"
placeholder="Search posts..."
/>
<button className="flex items-center justify-center px-4 bg-blue-500">
<svg
className="w-6 h-6 text-white"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</button>
</div>
</div>
{searchTerm &&
filteredPosts.map((post) => (
<div key={post.id} className="mt-10 text-lg">
<p>
<strong>Title:</strong> {post.title}
</p>
<p>
<strong>Body:</strong> {post.body}
</p>
</div>
))}
</div>
);
}