Я пытаюсь реализовать панель поиска в реальном времени с помощью Next.js. Я могу обработать изменение ввода, но я не могу отфильтровать свои результаты на основе ввода.
макет.jsx:
import './globals.css';
import SearchBar from './SearchBar';
export const metadata = {
title: 'My App',
description: 'Generated by create next app',
}
export default function RootLayout({ children }) {
return (
<html lang = "en">
<body className='text-center bg-sky-800'>
<h1 className='text-4xl mt-4 text-white'>My App</h1>
<SearchBar />
{children}
</body>
</html>
)
}
Компонент панели поиска:
'use client'
import { useState } from "react"
export default function SearchBar() {
const [searchInput, setSearchInput] = useState('');
function handleChangeEvent(e) {
setSearchInput(e.target.value);
}
return (
<input
className = "p-3 border rounded bg-blue-100"
type = "search"
placeholder = "Search Robots"
onChange = {handleChangeEvent}
/>
)
}
Компонент, содержащий код элементов, которые я хочу отфильтровать (это карточки):
import Card from './Card'
import { robots } from './robots'
export default function RobotList() {
return (
<main>
{robots.map(robot => {
return (
<Card key = {robot.id} id = {robot.id} name = {robot.name} email = {robot.email} />
)
})
}
</main>
)
}
страница.jsx:
import RobotList from './RobotList'
export default function Home() {
return (
<main>
<RobotList />
</main>
)
}
Карточный компонент:
export default function Card({ id, name, email }) {
return (
<div className = "text-center bg-green-300 p-3 rounded inline-block m-2 hover:scale-105 transition ease-in duration-300 drop-shadow-xl">
<img src = {`https://robohash.org/${id}?200x200`} alt = "robot" />
<div>
<h2>{name}</h2>
<p>{email}</p>
</div>
</div>
)
}
Я использую Next.js v13. Любая помощь будет оценена по достоинству. Спасибо :)



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Что касается вашего текущего кода, компонент, отображающий список robots, вообще не привязан к input. Один из способов реализовать поиск, который не сильно изменит структуру ваших текущих компонентов, — это преобразовать SearchBar в поставщика контекста, который вернет отфильтрованный robots.
Я назвал это RobotsContextProvider:
// RobotsContextProvider.js
"use client";
// Make sure this is the correct path
import { robots } from "./robots";
import { useState, createContext, useContext } from "react";
const RobotsContext = createContext();
export function useRobotsContext() {
return useContext(RobotsContext);
}
export default function RobotsContextProvider({ children }) {
const [searchInput, setSearchInput] = useState("");
function handleChangeEvent(e) {
setSearchInput(e.target.value);
}
return (
<RobotsContext.Provider
value = {{ robots: searchInput ? robots.filter((r) => r.name.includes(searchInput)) : robots }}
>
<input
className = "p-3 border rounded bg-blue-100"
type = "search"
placeholder = "Search Robots"
onChange = {handleChangeEvent}
/>
{children}
</RobotsContext.Provider>
);
}
Вы оборачиваете его children в RootLayout:
import "./globals.css";
import RobotsContextProvider from "./RobotsContextProvider";
export const metadata = {
title: "My App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang = "en">
<body className = "text-center bg-sky-800">
<h1 className = "text-4xl mt-4 text-white">My App</h1>
<RobotsContextProvider>{children}</RobotsContextProvider>
</body>
</html>
);
}
В RobotList вы используете robots из контекста, а не импортируете его:
"use client";
import Card from "./Card";
// Make sure this is the correct path
import { useRobotsContext } from "./RobotsContextProvider";
export default function RobotList() {
const { robots } = useRobotsContext();
return (
<main>
{robots.map((robot) => {
return <Card key = {robot.id} id = {robot.id} name = {robot.name} email = {robot.email} />;
})}
</main>
);
}
Убедитесь, что вы читаете комментарии.
Большое спасибо @Youssouf, все отлично работает! Я обязательно прочитаю больше о контекстах React.