根据查询字符串过滤数据时,如何避免刷新页面时组件首次渲染?

Ole*_*kyi 5 javascript reactjs next.js

我有一个表组件:

import { useState, useEffect, useRef } from 'react';
import data from '@/data.json';
import { useRouter } from 'next/router'

import styles from './table.module.css';

export default function Table() {
  const firstUpdate = useRef(true);
  let [tableDate, updateTableDate] = useState([]);

  const router = useRouter();
  
  useEffect(() => {
    if (firstUpdate.current) {
      firstUpdate.current = false;
      return;
    }

    updateTableDate(() => {
      const result = router.query.search ? data.filter((item) => item.title.toLowerCase().match(router.query.search.toLowerCase())) : data;
      return result;
    });    
  }, [router.query.search]);
  
  return (
    <>
      <div className={styles.table}>
        <table>
          <thead>
            <tr>
              <th>
                Title
              </th>           
            </tr>
          </thead>
          <tbody>
            {tableDate.map((item, i) =>
              <tr key={item.id}>
                <td>
                   {item.title}            
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </>
  );
}
Run Code Online (Sandbox Code Playgroud)

我有一个表和一个用于搜索查询的输入。该表呈现如下:

  • 如果搜索查询为空,或者我刚刚进入结果页面,那么我将看到所有数据;
  • 如果我在搜索中输入某些内容 - 数据将根据搜索查询字符串进行过滤。

在以下情况下会出现此问题:
我输入了搜索查询,重建了表,然后重新加载页面。
此时,我首先看到所有数据是如何绘制的,只有在带有过滤数据的表格之后。如何避免呢?

You*_*mar 1

您首先获取完整的数据,然后对其进行过滤,因为在客户端上运行 JavaScript 来获取查询字符串并重新渲染组件需要一些时间。

您可以useEffect按如下方式更改您的。仅当路由器准备就绪时才更新数据,并且只要为tableDate空就不会显示任何内容(或加载程序)。

import { useState, useEffect, useRef } from 'react';
import data from '@/data.json';
import { useRouter } from 'next/router'

import styles from './table.module.css';

export default function Table() {
  let [tableDate, updateTableDate] = useState([]);

  const router = useRouter();

  useEffect(() => {
    updateTableDate(() => {
      if (!router.isReady) {
        return [];
      }
      const result = router.query.search
        ? data.filter((item) => item.title.toLowerCase().match(router.query.search.toLowerCase()))
        : data;
      return result;
    });
  }, [router]);

  if (tableDate.length <= 0) {
    // You could return a loading spinner if you want
    return null;
  }

  return <>Render your table</>;
}
Run Code Online (Sandbox Code Playgroud)