【问题标题】:Render countdowns on each flat list item在每个平面列表项上呈现倒计时
【发布时间】:2018-04-21 04:06:42
【问题描述】:

我正在使用 react-native 和 Firebase 做一个拍卖应用程序,我正在使用 FlatList 来呈现每个拍卖组件。

在每个拍卖组件想要显示带有提醒时间的倒计时,我正在从 Firebase 检索拍卖的结束日期。

但如果我每秒更新一次状态,我的每个拍卖组件的应用都会变得非常缓慢。

有更好的方法吗?

【问题讨论】:

  • 如果您希望倒计时以 1 秒的间隔刷新,那么您必须更新状态以每 1 秒重新渲染一次。如果您使用的是 FlatList,这不应该导致太多的性能问题。您的性能瓶颈可能在于其他问题。
  • 这就是 React 的亮点!协调概念就是这样,除非您的组件标签结构没有改变,否则实际上没有性能开销。这更像是更新元素属性。
  • 如果我有很多间隔为平面列表中的每个组件运行一个间隔,那没问题?因为当我不使用密码时,该应用程序可以完美运行。

标签: reactjs performance firebase react-native


【解决方案1】:

我有很多间隔为平面列表中的每个组件运行一个

您可以将计时器移动到带有FlatList 的组件,这样您就只有一个计时器。

还要确保在componentDidMount 中设置间隔并在componentWillUnmount 中清除。

class App extends React.Component {
  state = {
    timeElapsed: 0,
  };
  componentDidMount() {
    this.interavl = setInterval(
      () => this.setState((prev) => ({ timeElapsed: prev.timeElapsed + 1 })),
      1000,
    );
  }
  componentWillUnmount() {
    clearInterval(this.interval);
  }
  render() {
    return <FlatList renderItem={() => <Child timeElapsed={this.state.timeElapsed} />} />;
  }
}

const Child = (props) => <Text>{props.timeRemaining - props.timeElapsed}</Text>;

【讨论】:

    【解决方案2】:

    在我的拍卖应用程序中使用它:

    Timer.js

    /**
     * Timer Component
     */
    
    import React, {
      useState,
      useEffect,
      useRef,
      forwardRef,
      useImperativeHandle,
    } from 'react';
    import { Text, View } from 'react-native';
    
    const Timer = forwardRef((props, ref) => {
      // For Total seconds
      const [timeStamp, setTimeStamp] = useState(
        props.timestamp ? props.timestamp : 0,
      );
      // Delay Required
      const [delay, setDelay] = useState(props.delay ? props.delay : 1000);
    
      // Flag for informing parent component when timer is over
      const [sendOnce, setSendOnce] = useState(true);
    
      // Flag for final display time format
      const [finalDisplayTime, setFinalDisplayTime] = useState('');
    
      useInterval(() => {
        if (timeStamp > 0) {
          setTimeStamp(timeStamp - 1);
        } else if (sendOnce) {
          if (props.timerCallback) {
            props.timerCallback(true);
          } else {
            console.log('Please pass a callback function...');
          }
          setSendOnce(false);
        }
        setFinalDisplayTime(secondsToDhms(timeStamp));
      }, delay);
    
      function secondsToDhms(secs) {
        const d = Math.floor(secs / (3600 * 24));
        const h = Math.floor((secs / 3600) % 24);
        const m = Math.floor((secs / 60) % 60);
        const s = Math.floor(secs % 60);
        const dDisplay = d > 0 ? d + 'd ' : '';
        const hDisplay = h >= 0 ? h + 'h ' : '';
        const mDisplay = m >= 0 ? m + 'm ' : '';
        const sDisplay = s >= 0 ? s + 's' : '';
        return dDisplay + hDisplay + mDisplay + sDisplay;
      }
    
      const refTimer = useRef();
      useImperativeHandle(ref, () => ({
        resetTimer: () => {
          // Clearing days, hours, minutes and seconds
          // Clearing Timestamp
          setTimeStamp(props.timestamp);
          setSendOnce(true);
        },
      }));
    
      return (
        <View ref={refTimer} style={props.containerStyle}>
          <Text style={props.textStyle}>{sendOnce ? finalDisplayTime : '0'}</Text>
        </View>
      );
    });
    
    function useInterval(callback, delay) {
      const savedCallback = useRef();
    
      // Remember the latest function.
      useEffect(() => {
        savedCallback.current = callback;
      }, [callback]);
    
      // Set up the interval.
      useEffect(() => {
        function tick() {
          savedCallback.current();
        }
        if (delay !== null) {
          const id = setInterval(tick, delay);
          return () => {
            clearInterval(id);
          };
        }
      }, [delay]);
    }
    
    export default Timer;
    

    用法:

    <Timer
          timestamp={moment(auction_vehicles?.time_left).diff(moment(), 'seconds')} //should be in seconds
          //timerCallback={timerCallbackFunc}  //will be called after timer completes
          textStyle={styles.timerTextAHL}
        />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-27
      • 2020-01-21
      • 2022-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多