首页 > 解决方案 > React - 优化 JSX 元素的渲染数组

问题描述

我正在使用 React 17.0.2,我遇到了一个与如何渲染包含大量 JSX 元素的数组相关的性能问题(它可能从 100 到 ~650 个元素不等)。

特别是,我想在一个可滚动的容器中展示一定数量的不同“卡片”,其中每一个都包含一个图表、图像、图标和段落。每次 SSE 发送新数据时,这些细节都会发生变化。

下面的代码工作得很好,并且完成了我期望它做的事情,但渲染速度很慢。我正在开发的应用程序也应该在手机上使用,我担心等待对于用户来说有点太长了。

参赛者:

const Contestants = memo(() => {
  return (
    <div className={`${'contestants-container animate__animated animate__fadeIn'} ${classes.mainContainer}`}>
      <div className={`${'mx-0 my-0'} ${classes.cardsContainer}`}>
        <PerfectScrollbar>
          <div className='d-flex flex-wrap align-items-center justify-content-evenly' >
            <DetailCards />
          </div>
        </PerfectScrollbar>
      </div>
    </div>    
  )
})
export default Contestants

明细卡

const DetailCards = memo(() => {

 // ** Context
 const fetchDataContext = useContext(FetchDataContext)
 const vehicleData = fetchDataContext.vehicleData
 const locationData = fetchDataContext.locationData
 const payloadSSE = fetchDataContext.payloadSSE

 // ** State
 const [detailCardsArray, setDetailCardsArray] = useState([])
 const [initialLocationFlag, setInitialLocationFlag] = useState(true)
 const [initialLocationData, setInitialLocationData] = useState({})

 const detailCardsArrayRef = useRef(detailCardsArray)
 
 useEffect(() => {
   if (detailCardsArray) {
     detailCardsArrayRef.current = detailCardsArray
   }
 }, [detailCardsArray])

 useEffect(() => {
   setInitialLocationFlag(true)
 }, [])

 useEffect(() => {
   if (initialLocationFlag === true && Object.keys(locationData).length !== 0) {
     setInitialLocationData(locationData)
     setInitialLocationFlag(false)
   }
 }, [locationData, initialLocationFlag])

 useEffect(() => {
   if (Object.keys(vehicleData).length !== 0 && Object.keys(initialLocationData).length !== 0) {
     let temporaryDetailCardsArray = []
     for (let i = 0; i < Object.keys(vehicleData).length; i++) {
       temporaryDetailCardsArray.push(
         <DetailCard 
           key={vehicleData[Object.keys(vehicleData)[i]].imei} 
           object1={vehicleData[Object.keys(vehicleData)[i]]} 
           object2={initialLocationData[Object.keys(vehicleData)[i]]} 
         />
       )
     }
     setDetailCardsArray(temporaryDetailCardsArray)
   }
 }, [vehicleData, initialLocationData])

 useEffect(() => {
   if (detailCardsArrayRef.current.length !== 0) {
     if (typeof payloadSSE !== 'undefined' && payloadSSE !== null) {
       for (let i = 0; i < detailCardsArrayRef.current.length; i++) {
         if (detailCardsArrayRef.current[i].key === payloadSSE.imei) {
           detailCardsArrayRef.current[i] = (
             <DetailCard 
               key={detailCardsArrayRef.current[i].key} 
               object1={detailCardsArrayRef.current[i].props.object1} 
               object2={payloadSSE} 
             />
           )         
         }
       }
     }
     setDetailCardsArray(detailCardsArrayRef.current) 
   }
 }, [payloadSSE])
 
 return detailCardsArray
})

export default DetailCards

那么,有没有办法更快地渲染数组?我考虑过虚拟化,但我不确定如何实现它。

谢谢!

标签: arraysreactjsoptimization

解决方案


通过使用@Piotr Żak 建议来获取一定数量的元素并为用户提供加载更多元素的选项,该问题已得到解决。此外,我还添加了分页。现在它即使在手机上也能正常工作。


推荐阅读