MST

星途 面试题库

面试题:React列表过滤与排序同时实现的优化

在一个React应用中有一个列表,列表项包含多种属性,如 'name'(字符串)、'age'(数值)等。现在需要实现根据 'name' 模糊搜索过滤,以及根据 'age' 进行排序。在实现过程中,如何优化性能,避免不必要的重新渲染?请阐述思路并给出关键代码片段。
24.5万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

思路

  1. 使用 React.memo 包裹列表组件:React.memo 是一个高阶组件,它可以对函数式组件进行浅比较,只有当 props 发生变化时才会重新渲染组件,避免不必要的渲染。
  2. 合理使用 useState 和 useEffect:在状态更新时,确保只在必要时触发重新渲染。例如,对于搜索和排序的状态,只在相关值改变时才重新计算过滤和排序后的列表。
  3. 防抖(Debounce)处理搜索输入:当用户输入搜索内容时,频繁触发搜索操作会导致性能问题。使用防抖可以在用户停止输入一段时间后再执行搜索,减少不必要的计算。

关键代码片段

import React, { useState, useEffect, memo } from 'react';

// 模拟数据
const dataList = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 20 }
];

// 列表组件,使用 React.memo 优化
const ListItem = memo(({ item }) => {
  return (
    <li>
      Name: {item.name}, Age: {item.age}
    </li>
  );
});

const App = () => {
  const [searchText, setSearchText] = useState('');
  const [sortByAge, setSortByAge] = useState(false);
  const [filteredList, setFilteredList] = useState(dataList);

  // 防抖函数
  const debounce = (func, delay) => {
    let timer;
    return function() {
      const context = this;
      const args = arguments;
      clearTimeout(timer);
      timer = setTimeout(() => {
        func.apply(context, args);
      }, delay);
    };
  };

  const handleSearch = debounce((text) => {
    setSearchText(text);
    const newFilteredList = dataList.filter(item =>
      item.name.toLowerCase().includes(text.toLowerCase())
    );
    setFilteredList(newFilteredList);
  }, 300);

  useEffect(() => {
    if (sortByAge) {
      const sortedList = filteredList.sort((a, b) => a.age - b.age);
      setFilteredList(sortedList);
    } else {
      const newFilteredList = dataList.filter(item =>
        item.name.toLowerCase().includes(searchText.toLowerCase())
      );
      setFilteredList(newFilteredList);
    }
  }, [sortByAge, searchText]);

  return (
    <div>
      <input
        type="text"
        placeholder="Search by name"
        onChange={(e) => handleSearch(e.target.value)}
      />
      <button onClick={() => setSortByAge(!sortByAge)}>
        {sortByAge? 'Cancel Sort by Age' : 'Sort by Age'}
      </button>
      <ul>
        {filteredList.map((item, index) => (
          <ListItem key={index} item={item} />
        ))}
      </ul>
    </div>
  );
};

export default App;