Next.js中如何将搜索词参数传入getServerSideProps实现笔记筛选?
实现步骤
1. 修改笔记页面的getServerSideProps,接收URL查询参数
getServerSideProps可以通过入参的context对象获取当前页面的URL查询参数,我们直接从中取搜索词即可:
// 给getServerSideProps增加context参数 export async function getServerSideProps(context) { const allNotes = getAllNotes(); // 从URL查询参数取搜索词,无搜索词时默认是空字符串 const searchTerm = context.query.search || ""; // 原有过滤逻辑保持不变 const searchNotes = allNotes.filter((note) => { return note.data.title.toLowerCase().includes(searchTerm.toLowerCase()) || note.data.author.toLowerCase().includes(searchTerm.toLowerCase()) || note.data.abstract.toLowerCase().includes(searchTerm.toLowerCase()) }); return { props: { notes: searchNotes.map(({ data, content, slug }) => ({ ...data, content, slug, })), // 把当前搜索词传递给页面组件,用于回显到搜索框 currentSearch: searchTerm }, }; };
2. 修改Search组件,支持初始值回填和路由参数更新
搜索时不需要单独调用接口,直接修改当前页面的URL查询参数即可,Next.js会自动触发getServerSideProps重新执行,拿到新的过滤后的数据。此处增加防抖逻辑,避免输入过程中频繁触发页面刷新:
import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; // 补充导入SearchIcon,原代码漏了该引入 import SearchIcon from '@material-ui/icons/Search'; export default function Search({ initialValue }) { const [input, setInput] = useState(initialValue || ''); const router = useRouter(); // 防抖:输入停止300ms后再更新路由参数 useEffect(() => { const timer = setTimeout(() => { router.push({ pathname: router.pathname, query: { ...router.query, search: input } }, undefined, { shallow: false }) }, 300) return () => clearTimeout(timer) }, [input, router]) const search = (e) => { setInput(e.target.value); } return ( <div className={style.search}> <SearchIcon className={style.search__inputIcon}/> <input type="text" placeholder="搜索笔记..." value={input} onChange={search} /> </div> ) }
3. 修改Notes页面组件,传递当前搜索词到搜索组件
export default function Notes({ notes, currentSearch }) { return ( <div id="top" className={styles.container}> <Head></Head> <main className={styles.main}> <section> <Navigation /> </section> <section className={noteStyle.noteSection}> <h1>笔记与摘要</h1> {/* 把当前搜索词传递给搜索组件作为初始值,刷新页面不会丢失搜索内容 */} <Search initialValue={currentSearch}/> {/* 原有笔记渲染逻辑保持不变 */} <div className={noteStyle.notes}> {notes.map((note) => ( <Link key={note.slug} href={`/note/${note.slug}`}> <a key={note.slug} className={noteStyle.noteCard}> <h2 key="title">{note.title}</h2> <h3 key="author">{note.author}</h3> <p key="abstract"> {note.abstract} </p> <div className={noteStyle.aboutNote}> <Rating key="rating" className={noteStyle.rating} name="half-rating-read" defaultValue={note.rating} precision={0.5} readOnly /> <Chip key="label" className={noteStyle.noteChip} bgColor={note.labelColors[0]} text={note.labelText[0]} icon={note.labelIcons[0]} /> </div> </a> </Link> ))} </div> </section> </main> <Footer /> </div> ) }
逻辑说明
整个实现没有把服务端的getAllNotes逻辑暴露到客户端,所有数据过滤都在服务端完成:
- 用户在搜索框输入内容,防抖结束后自动更新当前页面URL的
search查询参数 - URL参数变更触发
getServerSideProps重新执行,读取最新的search参数过滤笔记 - 过滤后的笔记数据返回给页面组件重新渲染,完成搜索效果
内容的提问来源于stack exchange,提问作者Simon Wilmots
相关产品推荐
相关产品推荐

