我有一个大约100行的mySQL数据库,其中包含我在电子商务应用程序中列出的产品数据。
我使用Axios从后端SELECT *
语句中获取行,将它们显示在前端,然后将它们保存为数组状态const [rows, setRows] = useState([]);
,然后将这些行Map到表中的每一行,因此大约有100个Map。
我已经注意到,在这么多的结果中,性能已经开始成为一个问题,我也从Map数组中听到过类似的问题。我已经进行了基准测试和修补,发现这个组件是导致性能问题的原因。我希望有任何解决方案来提高我的组件的性能,而不需要太多地改变结构。
这是组件
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import Button from '@mui/material/Button';
export default function ProductCard(props) {
const [rows, setRows] = useState([]);
const isntDesktop = props.isntDesktop; //Constant from parent
const isMobile = window.innerWidth < 768; //Checks if screen is smaller than mobile
const sidebar = props.sidebar; //Sidebar state from parent component
useEffect(() => {
axios.get('http://localhost:8080/products/get/')
.then(res => {
setRows(res.data);
}).catch(err => {
console.log(err);
});
});
return (
rows
.sort((a, b) => a.name.localeCompare(b.name))
//Map products
.map((row, index) => {
return (
/* Adjust structure for mobile */
isMobile ? (
/* Product card */
<div
key={index}
class={`${
sidebar ? 'border-0' : 'border'
} relative mt-6 py-8 px-5 rounded`}
>
{/* Heading */}
<h2 class="text-2xl font-semibold tracking-wide text-gray-700">{row.name}</h2>
<div class="flex items-center sm:items-start space-x-5">
{/* Image */}
<img
src={row.image}
alt="product"
class={`${
sidebar ? 'opacity-50' : 'opacity-100'
} mt-4 min-w-[125px] sm:w-[300px] h-auto`}
/>
<div class="mt-4">
{/* Price */}
<p class="text-2xl sm:text-xl font-semibold sm:font-medium text-gray-600">£ {row.price}</p>
{/* Keywords */}
<ul class="ml-5 mt-2 space-y-1">
<li class="list-disc text-gray-600">{row.keyword_one}</li>
<li class="list-disc text-gray-600" >{row.keyword_two}</li>
<li class="list-disc text-gray-600">{row.keyword_three}</li>
</ul>
</div>
</div>
<div
class={`${
sidebar ? 'bg-none' : 'bg-gray-100'
} mt-4 py-2 px-4 flex justify-center space-x-2.5`}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-sky-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 18.75a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h6m-9 0H3.375a1.125 1.125 0 01-1.125-1.125V14.25m17.25 4.5a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h1.125c.621 0 1.129-.504 1.09-1.124a17.902 17.902 0 00-3.213-9.193 2.056 2.056 0 00-1.58-.86H14.25M16.5 18.75h-2.25m0-11.177v-.958c0-.568-.422-1.048-.987-1.106a48.554 48.554 0 00-10.026 0 1.106 1.106 0 00-.987 1.106v7.635m12-6.677v6.677m0 4.5v-4.5m0 0h-12" />
</svg>
<label class="text-gray-600 text-sm">Free delivery on orders over £50</label>
</div>
<div class="mt-4 w-full mx-auto flex flex-col sm:flex-row space-y-2.5 sm:space-y-0 sm:space-x-2.5">
{sidebar && isntDesktop ? (
<Button
type="submit"
variant="contained"
sx={{
opacity: 0.5,
bgcolor: '#6366f1',
textTransform: 'none',
width: '100%',
':hover': {
backgroundColor: '#4f46e5',
},
}}
>
View product
</Button>
) : (
<Button
type="submit"
variant="contained"
sx={{
opacity: 1,
bgcolor: '#6366f1',
textTransform: 'none',
width: '100%',
':hover': {
backgroundColor: '#4f46e5',
},
}}
>
View product
</Button>
)}
<Button
type="submit"
sx={{
border: ' 1px solid #38bdf8',
color: '#38bdf8',
textTransform: 'none',
width: '100%',
':hover': {
color: '#ffffff',
backgroundColor: '#38bdf8',
},
}}
>
Add to cart
</Button>
</div>
</div>
) : (
<div key={index} class="flex mt-6 py-8 px-5 border rounded">
{/* Image */}
<img src={row.image} alt="product" class="mr-4 w-[300px] h-auto" />
<div class="relative w-full px-5 items-center">
{/* Heading */}
<h2 class="text-2xl font-semibold tracking-wide text-gray-700">{row.name}</h2>
<div class="mt-8 flex justify-between">
{/* Keywords */}
<ul class="ml-5 space-y-1">
<li class="list-disc text-gray-600">{row.keyword_one}</li>
<li class="list-disc text-gray-600" >{row.keyword_two}</li>
<li class="list-disc text-gray-600">{row.keyword_three}</li>
</ul>
{/* Promo */}
<div class="flex flex-col ml-5">
{/* Price */}
<p class="text-xl font-medium text-gray-600">£ {row.price}</p>
<div
class={`${
sidebar ? 'bg-none' : 'bg-gray-100'
} mt-4 py-2 px-4 flex space-x-2.5`}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-sky-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 18.75a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h6m-9 0H3.375a1.125 1.125 0 01-1.125-1.125V14.25m17.25 4.5a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h1.125c.621 0 1.129-.504 1.09-1.124a17.902 17.902 0 00-3.213-9.193 2.056 2.056 0 00-1.58-.86H14.25M16.5 18.75h-2.25m0-11.177v-.958c0-.568-.422-1.048-.987-1.106a48.554 48.554 0 00-10.026 0 1.106 1.106 0 00-.987 1.106v7.635m12-6.677v6.677m0 4.5v-4.5m0 0h-12" />
</svg>
<label class="text-gray-600 text-sm">Free delivery on orders over £50</label>
</div>
</div>
</div>
<div class="absolute bottom-0 w-full pr-5 flex space-x-2.5">
{sidebar && isntDesktop ? (
<Button
type="submit"
variant="contained"
sx={{
opacity: 0.5,
bgcolor: '#6366f1',
textTransform: 'none',
width: '100%',
':hover': {
backgroundColor: '#4f46e5',
},
}}
>
View product
</Button>
) : (
<Button
type="submit"
variant="contained"
sx={{
opacity: 1,
bgcolor: '#6366f1',
textTransform: 'none',
width: '100%',
':hover': {
backgroundColor: '#4f46e5',
},
}}
>
View product
</Button>
)}
<Button
type="submit"
sx={{
border: ' 1px solid #38bdf8',
color: '#38bdf8',
textTransform: 'none',
width: '100%',
':hover': {
color: '#ffffff',
backgroundColor: '#38bdf8',
},
}}
>
Add to cart
</Button>
</div>
</div>
</div>
)
)
})
)
}
1条答案
按热度按时间z0qdvdin1#
由于你(可能)希望只提取一次数据(在装载时),你必须在
useEffect
中添加一个空的依赖关系数组,以避免无休止地运行一个查询。你可以在这里阅读更多关于它的内容:https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects(在“注意”部分)。我看到你在render上呈现所有的数据,不幸的是,React is notoriously slow when it comes to rendering large lists。你可能需要考虑
windowing
你的数据,也就是当你的页面第一次加载时呈现一大块数据,当用户向下滚动时呈现更多的数据。有一个很棒的库可以为你处理这个问题:是的。我希望这对你有帮助!