基于查询字符串过滤数据时,如何避免页面刷新时组件首次渲染全量数据?
问题解决:避免刷新页面时表格先显示全量再过滤
问题根源
刷新页面时,Next.js 的 router.query 不会立即加载完成,再加上你的代码通过 firstUpdate 跳过了第一次 useEffect 执行,导致表格初始状态为空,等 router.query 就绪后才会先设置成全量数据(若搜索参数存在,后续又会更新为过滤后的数据),从而出现数据闪烁的问题。
修复方案
直接在初始化状态时就根据 router.query.search 过滤数据,同时利用 router.isReady 确保路由参数就绪后再渲染表格,避免初始空状态或不必要的重复更新:
import { useState, useEffect } from 'react'; import data from '@/data.json'; import { useRouter } from 'next/router' import styles from './table.module.css'; export default function Table() { const router = useRouter(); // 初始状态直接根据搜索参数过滤数据,路由未就绪时先返回空数组 const [tableData, setTableData] = useState(() => { if (!router.isReady) return []; return router.query.search ? data.filter(item => item.title.toLowerCase().includes(router.query.search.toLowerCase())) : data; }); useEffect(() => { // 路由参数变化时更新表格数据 if (router.isReady) { const filteredData = router.query.search ? data.filter(item => item.title.toLowerCase().includes(router.query.search.toLowerCase())) : data; setTableData(filteredData); } }, [router.isReady, router.query.search]); // 路由未就绪时可显示加载状态,避免空表格闪烁 if (!router.isReady) { return <div>加载中...</div>; } return ( <div className={styles.table}> <table> <thead> <tr> <th>Title</th> </tr> </thead> <tbody> {tableData.map((item) => ( <tr key={item.id}> <td>{item.title}</td> </tr> ))} </tbody> </table> </div> ); }
关键改动说明
- 初始状态预计算:利用
useState的初始化函数,结合router.isReady直接生成对应状态,无需等待useEffect触发才更新数据。 - 依赖
router.isReady:确保路由参数完全就绪后再处理数据和渲染表格,避免router.query未就绪导致的错误或异常状态。 - 移除
firstUpdate:不再跳过第一次useEffect执行,而是通过路由就绪状态控制逻辑,保证参数变化时总能正确更新数据。 - 替换
match为includes:match属于正则匹配,若搜索内容包含特殊字符可能引发错误,includes更适合简单的模糊搜索场景。
内容的提问来源于stack exchange,提问作者Oleksii Binetskyi
相关产品推荐
相关产品推荐

