You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中双.map渲染数据致页面卡顿,寻求性能优化方案

优化双列表渲染的性能问题

核心问题分析

你的代码目前存在几个关键问题,会随着数据量增长加剧性能损耗:

  • useEffect 未设置依赖数组,导致每次组件渲染都会重复发起两次API请求,不仅浪费资源,还会触发不必要的状态更新和重渲染
  • 列表渲染时未提供唯一key,React无法高效识别列表项的变化,会导致全量重渲染
  • deleteRow 逻辑错误:依赖全局data状态而非当前行的test值,点击删除按钮时可能删除错误数据
  • 内联渲染列表项,没有利用React的组件缓存机制,每次父组件重渲染都会重新创建所有列表元素

优化方案与代码实现

1. 修复无限API请求

给useEffect添加空依赖数组,确保仅在组件挂载时请求一次数据,同时用Promise.all并行请求提升加载效率:

useEffect(() => {
  Promise.all([
    axios.get('/users/get'),
    axios.get('/products/get/')
  ])
  .then(([userRes, productRes]) => {
    setUserRows(userRes.data);
    setProductRows(productRes.data);
  })
  .catch(err => console.log(err));
}, []); // 空依赖数组:仅挂载时执行

2. 添加列表项唯一Key

React需要key来追踪列表元素的身份,避免不必要的DOM操作(建议用数据库主键作为key,如果row.test/row.name不唯一的话):

{userRows.map((row) => (
  <UserRow key={row.test} row={row} onDelete={deleteRow} />
))}

{productRows.map((row) => (
  <ProductRow key={row.name} row={row} />
))}

3. 提取独立子组件并使用React.memo缓存

将列表项渲染逻辑提取为独立组件,并用React.memo包裹,只有当props变化时才会重渲染:

// 缓存用户行组件
const UserRow = React.memo(({ row, onDelete }) => (
  <div>
    <p>{row.test}</p>
    <button onClick={() => onDelete(row.test)}>Delete</button>
  </div>
));

// 缓存产品行组件
const ProductRow = React.memo(({ row }) => (
  <div>
    <p>{row.name}</p>
    {/* 渲染产品图片 */}
    {/* {row.imageSrc && <img src={row.imageSrc} alt={row.name} />} */}
  </div>
));

4. 修正deleteRow逻辑并更新本地状态

删除成功后直接更新本地userRows,避免重新请求数据,同时修正参数传递逻辑:

const deleteRow = (testValue) => {
  axios.delete(`/users/delete/${testValue}`)
    .then(() => {
      // 删除成功后过滤本地列表
      setUserRows(prevRows => prevRows.filter(row => row.test !== testValue));
    })
    .catch(err => console.log(err));
};

5. 优化insertRow逻辑(可选)

插入成功后更新本地状态并清空输入框,提升用户体验:

const insertRow = () => {
  if (!data.trim()) return; // 空值不提交
  axios.post('/users/insert', { row: data })
    .then(res => {
      setUserRows(prev => [...prev, res.data]);
      setData('');
    })
    .catch(err => console.log(err));
};

完整优化后代码

import React, { useState, useEffect, memo } from 'react';
import axios from 'axios';
import Helmet from 'react-helmet';

// 缓存用户行组件
const UserRow = memo(({ row, onDelete }) => (
  <div>
    <p>{row.test}</p>
    <button onClick={() => onDelete(row.test)}>Delete</button>
  </div>
));

// 缓存产品行组件
const ProductRow = memo(({ row }) => (
  <div>
    <p>{row.name}</p>
    {/* 渲染产品图片 */}
    {/* {row.imageSrc && <img src={row.imageSrc} alt={row.name} />} */}
  </div>
));

export default function Database() {
  const [userRows, setUserRows] = useState([]);
  const [productRows, setProductRows] = useState([]);
  const [data, setData] = useState('');

  useEffect(() => {
    Promise.all([
      axios.get('/users/get'),
      axios.get('/products/get/')
    ])
    .then(([userRes, productRes]) => {
      setUserRows(userRes.data);
      setProductRows(productRes.data);
    })
    .catch(err => console.log(err));
  }, []);

  const insertRow = () => {
    if (!data.trim()) return;
    axios.post('/users/insert', { row: data })
      .then(res => {
        setUserRows(prev => [...prev, res.data]);
        setData('');
      })
      .catch(err => console.log(err));
  };

  const deleteRow = (testValue) => {
    axios.delete(`/users/delete/${testValue}`)
      .then(() => {
        setUserRows(prev => prev.filter(row => row.test !== testValue));
      })
      .catch(err => console.log(err));
  };

  return (
    <>
      <Helmet>
        <title>Title | Database</title>
      </Helmet>
      
      <input className="mt-60" type="text" value={data} onChange={(e) => setData(e.target.value)} />
      <button onClick={insertRow}>Submit</button>

      {userRows.map((row) => (
        <UserRow key={row.test} row={row} onDelete={deleteRow} />
      ))}

      {productRows.map((row) => (
        <ProductRow key={row.name} row={row} />
      ))}
    </>
  );
};

额外性能建议

  • 如果数据量极大(数千条以上),考虑实现虚拟滚动,只渲染可视区域内的列表项
  • 对API请求添加缓存策略,避免重复请求相同数据
  • 确保后端接口返回的数据结构精简,只返回前端需要的字段,减少数据传输量

内容的提问来源于stack exchange,提问作者Josh Haywood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 02:35:19