我目前正在学习 NextJS 和 React,并且我一直在努力弄清楚如何制作输入搜索过滤器来过滤表格。
我看过很多关于使用 useSearchParams 的视频和评论,但这不是我想做的事情。
我想实时过滤,每次用户在输入上按下一个键时都会刷新表,并且随着我在输入过滤器中写入更多内容,行数会减少。
我该怎么办?
这是我的搜索输入文件:
"use client"
import { Input } from "@/components/ui/input"
import { useState} from 'react';
export default function InputSearch() {
const [search, setSearch] = useState('')
return(
<Input
placeholder="Buscar categoría..."
onChange={(e) => setSearch(e.target.value)}
value={search}
/>
)
}
这是我的 page.tsx 文件(服务器组件)
import Navbar from "@/components/navbar";
import {Heading} from "@/components/ui/heading"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
import {Button} from "@/components/ui/button"
import {db} from "@/lib/db"
import InputSearch from "@/app/table/categorias/components/search-input";
const SearchCategoryPage = async() => {
const categorias = await db.table_Categories.findMany({
orderBy: {
name: "asc",
}
})
const subcategorias = await db.table_Subcategories.findMany({
orderBy: {
name: "asc",
}
})
return(
<div>
<Navbar></Navbar>
<Heading
title="Categorías"
description="Description"
/>
<div className="pl-4 pr-4 w-[100%]">
<InputSearch/>
<Accordion type="single" collapsible className="w-full">
{categorias
.map((filteredCategoria) => (
<AccordionItem key={filteredCategoria.id} value={filteredCategoria.name}>
<AccordionTrigger>{filteredCategoria.name}</AccordionTrigger>
<AccordionContent>
{subcategorias
.filter((subcategoria) => subcategoria.id_category === filteredCategoria.id)
.map((filteredSubcategoria) => (
<div>
<Button variant="link" key={filteredSubcategoria.id}>{filteredSubcategoria.name}</Button>
</div>
))}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</div>
)
}
export default SearchCategoryPage
提前致谢!
嗨。
我目前正在学习 NextJS 和 React,并且我一直在尝试弄清楚如何制作输入搜索过滤器来过滤表格。
我看过很多关于使用 useSearchParams 的视频和评论,但这不是我想做的事情。
我想实时过滤,每次用户在输入上按下一个键时都会刷新表,并且随着我在输入过滤器中写入更多内容,行数会减少。
我该怎么办?
这是我的搜索输入文件:
"use client"
import { Input } from "@/components/ui/input"
import { useState} from 'react';
export default function InputSearch() {
const [search, setSearch] = useState('')
return(
<Input
placeholder="Buscar categoría..."
onChange={(e) => setSearch(e.target.value)}
value={search}
/>
)
}
这是我的 page.tsx 文件(服务器组件)
import Navbar from "@/components/navbar";
import {Heading} from "@/components/ui/heading"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
import {Button} from "@/components/ui/button"
import {db} from "@/lib/db"
import InputSearch from "@/app/table/categorias/components/search-input";
const SearchCategoryPage = async() => {
const categorias = await db.table_Categories.findMany({
orderBy: {
name: "asc",
}
})
const subcategorias = await db.table_Subcategories.findMany({
orderBy: {
name: "asc",
}
})
return(
<div>
<Navbar></Navbar>
<Heading
title="Categorías"
description="Description"
/>
<div className="pl-4 pr-4 w-[100%]">
<InputSearch/>
<Accordion type="single" collapsible className="w-full">
{categorias
.map((filteredCategoria) => (
<AccordionItem key={filteredCategoria.id} value={filteredCategoria.name}>
<AccordionTrigger>{filteredCategoria.name}</AccordionTrigger>
<AccordionContent>
{subcategorias
.filter((subcategoria) => subcategoria.id_category === filteredCategoria.id)
.map((filteredSubcategoria) => (
<div>
<Button variant="link" key={filteredSubcategoria.id}>{filteredSubcategoria.name}</Button>
</div>
))}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</div>
)
}
export default SearchCategoryPage
有多种方法可以实现这种方法。其中之一是使用状态管理,如
useContext
或 redux
来获取用户输入的搜索值并传递到所需的组件。不过,我建议使用 URL 搜索参数,这意味着将用户的输入查询转换为 URL 搜索查询。这样当前页面就可以直接访问这个变量了。 Next.js官方文档也推荐了这种方法。您可以参考https://nextjs.org/learn/dashboard-app/adding-search-and-pagination
// InputSearch
"use client"
import { Input } from "@/components/ui/input"
import { useSearchParams } from 'next/navigation'
export default function InputSearch() {
const params = new URLSearchParams(searchParams)
return(
<Input
placeholder="Buscar categoría..."
onChange={(e) => {
if (e.target.value) {
params.set('query', e.target.value);
} else {
params.delete('query');
}
}}
value={params.query}
/>
)
}
// SearchCategoryPage
.
.
.
import InputSearch from "@/app/table/categorias/components/search-input";
const SearchCategoryPage = async({searchParams}) => {
const query = searchParams?.query || '';
const categorias = await db.table_Categories.findMany({
orderBy: {
name: "asc",
},
// do your search query...
})
const subcategorias = await db.table_Subcategories.findMany({
orderBy: {
name: "asc",
},
// do your search query...
})
return(
<div>
<Navbar></Navbar>
<Heading
title="Categorías"
description="Description"
/>
<div className="pl-4 pr-4 w-[100%]">
<InputSearch/>
<Accordion type="single" collapsible className="w-full">
{categorias
.map((filteredCategoria) => (
<AccordionItem key={filteredCategoria.id} value={filteredCategoria.name}>
<AccordionTrigger>{filteredCategoria.name}</AccordionTrigger>
<AccordionContent>
{subcategorias
.filter((subcategoria) => subcategoria.id_category === filteredCategoria.id)
.map((filteredSubcategoria) => (
<div>
<Button variant="link" key={filteredSubcategoria.id}>{filteredSubcategoria.name}</Button>
</div>
))}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</div>
)
}
export default SearchCategoryPage