繁体   English   中英

在FlatList中反应本机计数计时器

[英]React Native Count up Timer inside FlatList

嗨,我是 React Native 的新手,现在我正在尝试在每个 Flat List 行中创建计数计时器。 基于数据时间戳的计算与当前日期进行比较。 我的倒计时间隔适用于每一行,但现在的问题是性能。 在 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

很少有关于如何优化代码的提示。

  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 去掉它。 这是没有用的。 useEffect的 return 语句上clearTimeout

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

// 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} 
/>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM