【问题标题】:React Native Count up Timer inside FlatList在 FlatList 中 React Native Count up Timer
【发布时间】:2020-10-05 03:51:30
【问题描述】:

您好,我是 React Native 的新手,现在我正在尝试在每个平面列表行中创建计数计时器。基于数据时间戳的计算与当前日期进行比较。我的倒计时间隔适用于每一行,但现在的问题是性能。在 Android 中有时会导致 ANR(应用程序无响应)。

我有什么建议可以改进此代码吗?非常感谢任何帮助。 谢谢。

  import React, { useState, useEffect } from 'react'
    import { View, Text, ActivityIndicator, Modal, FlatList } from 'react-native'
    import Style from '../../../../constants/Style'
    import AsyncStorage from '@react-native-community/async-storage'
    import { API, Auth } from 'aws-amplify'
    import AWSMQTTConnection from '../../../../common/AWSMQTTConnection'
    import AsyncStorageConstants from '../../../../constants/AsyncStorageConstants'
    
    var isLeaving = false
    
    
    function EquipmentElement({ id, name, number, status, time, maintenanceCode }) {
    
        const [hours, setHours] = useState('00')
        const [minutes, setMinutes] = useState('00')
        const [seconds, setSeconds] = useState('00')
    
        var count = setInterval(() => {
            var now = new Date().getTime()
            var distance = now - time
    
            var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
            var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60))
            var seconds = Math.floor((distance % (1000 * 60)) / 1000)
    
            var isHourLessThanTen = hours < 10
            var isMinuteLessThanTen = minutes < 10
            var isSecondLessThanTen = seconds < 10
    
            if (isHourLessThanTen) {
                hours = '0' + hours
            }
    
            if (isMinuteLessThanTen) {
                minutes = '0' + minutes
            }
    
            if (isSecondLessThanTen) {
                seconds = '0' + seconds
            }
    
    
            if ((status == 'Available' || status == undefined) || maintenanceCode == 1) {
                clearInterval(count)
            } else {
                if (isLeaving) {
                    clearInterval(count)
                } else {
                    setHours(hours)
                    setMinutes(minutes)
                    setSeconds(seconds)
                }
            }
    
        }, 1000)
    
    
        const setDurationValue = () => {
            if (maintenanceCode == 1) {
                <Text style={Style.value}>00:00:00</Text>
            } else {
                if (time != 0 || time != '' || time == undefined) {
                    return (<Text style={Style.value}>{hours}:{minutes}:{seconds}</Text>)
    
                } else {
                    return (<Text style={Style.value}>00:00:00</Text>)
                }
            }
        }
    
        return (
            <View style={Style.smartElementContainer}>          
                 {setDurationValue()}                  
            </View>
        )
    }
    
    function Equipment() {
    
        const [equipmentData, setEquipmentData] = useState([])
      
        useEffect(() => {
    
            isLeaving = false
            getEquipmentList(false)
    
            return function cleanup() {
                console.log('unmounting...')
                isLeaving = true
                setEquipmentData([])
            }
    
        }, [])

 const getEquipmentList = async (isMQTT) => {
        try {
           
            let propertyId = await AsyncStorage.getItem(AsyncStorageConstants.StorageConstants.CURRENT_PROPERTY_ID)
            let apiName = 'DemoAsiaIoT'
            let path = '/scdevice'
            let request = {
                headers: { Authorization: `Bearer ${(await Auth.currentSession()).getIdToken().getJwtToken()}` },
                response: true,
                queryStringParameters: {
                    propertyId: propertyId,
                    applicationId: 5
                }
            }

            await API.get(apiName, path, request).then(response => {
                var data = response.data.resultData
                var devices = []

                for (var i = 0; i < data.length; i++) {
                    var device = data[i]
                    devices.push({ id: device.deviceEUI, name: device.deviceName, number: '01', status: device.status, time: device.timestampStart, maintenanceCode: device.manualOverRide })
        
                }

                setEquipmentData(devices)
                
            }).catch(error => {
                console.log('Error from request - ', error.response)
            })


        } catch (err) {
            console.log('error:', err)
        }
    }

    
            return (
            <View style={{ flex: 1 }}>
                <FlatList
                    style={{
                        width: '100%',
                        marginTop: 10,
                    }}
                    showsVerticalScrollIndicator={false}
                    vertical={true}
                    data={equipmentData}
                    renderItem={({ item }) => <EquipmentElement id={item.id} name={item.name} number={item.number} status={item.status} time={item.time} maintenanceCode={item.maintenanceCode} />}
                    keyExtractor={item => item.id} />
            </View>
        )
    }
    
    export default Equipment

【问题讨论】:

  • 你的 FlatList 是如何在这里获取设备数据的?数据从何而来?
  • 嗨@PrateekThapa 感谢您的回复,我编辑了我的代码以显示如何获取设备数据。您可以在函数 getEquipmentList 中看到。

标签: android react-native setinterval react-native-flatlist countdownjs.js


【解决方案1】:

关于如何优化代码的一些提示。

  1. 您无需使用hoursminutesseconds 三个状态来在您的FlatList 项目中显示您的时间。这些是来自Date.now() 的派生词。你可以检查下面的代码来理解这个概念。只需在组件范围之外创建一个帮助函数,该函数会返回要显示的格式化时间。如果你这样做,你的大部分表现都可以得到解决。
function calculateTimeLeft() {
  const year = new Date().getFullYear();
  const difference = +new Date(`${year}-10-1`) - +new Date();
  let timeLeft = {};

  if (difference > 0) {
    timeLeft = {
      days: Math.floor(difference / (1000 * 60 * 60 * 24)),
      hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
      minutes: Math.floor((difference / 1000 / 60) % 60),
      seconds: Math.floor((difference / 1000) % 60)
    };
  }

  return timeLeft;
}

function FlatListItem() {
  const [timeLeft, setTimeLeft] = React.useState(calculateTimeLeft());

  React.useEffect(() => {
    const id = setTimeout(() => {
      setTimeLeft(calculateTimeLeft());
    }, 1000);

    return () => {
      clearTimeout(id);
    };
  });

  const timerComponents = Object.keys(timeLeft).map(interval => {
    if (!timeLeft[interval]) {
      return;
    }

    return (
      <span>
        {timeLeft[interval]} {interval}{" "}
      </span>
    );
  });
  1. 我不知道为什么要在您的组件中设置isLeaving。去掉它。这是没有用的。 clearTimeout 来自useEffect 的退货声明。

  2. 使用来自StyleSheet.create 的样式。创建一个函数keyExtractor 并将其放置在您的组件之外。并将 item 作为道具传递。

// outside the scope of your component
function keyExtractor(item) {
  return item.id;
}

<FlatList
     style={styles.flatlist} // place your styles in `StyleSheet.create`
     showsVerticalScrollIndicator={false}
     vertical={true}
     data={equipmentData}
     renderItem={EquipmentElement} // pass the item as a prop
     keyExtractor={keyExtractor} 
/>

【讨论】:

  • 嗨,Prateek,非常感谢您的建议,我会在上面尝试一下,看看我的情况如何。
猜你喜欢
  • 1970-01-01
  • 2018-04-05
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-03
相关资源
最近更新 更多