实时响应本机更新营业时间的状态

时间:2020-08-14 19:31:48

标签: reactjs react-native

我正在为React Native应用程序构建一个微型组件,该组件将根据企业的当前时间和营业时间数据显示企业当前是否营业。 应该很容易吧?好吧,到目前为止:)

我的要求:

  1. 我想让这个组件保持清晰(简单)并且尽可能短
  2. 必须将性能放在首位,因此我决定使用ref更新“打开/关闭”文本,而不是重新渲染。每秒为多个企业重新渲染此组件将立即使该应用程序崩溃(重新渲染次数过多)。

这是我到目前为止的去处:

import React, { useRef, useEffect, useCallback } from 'react';
import { TextInput, View } from 'react-native';
    
type FromTo = {
  from: number;
  to: number;
};
type opening_hours = {
  monday: FromTo;
  tuesday: FromTo;
  wednesday: FromTo;
  thursday: FromTo;
  friday: FromTo;
  saturday: FromTo;
  sunday: FromTo;
};

function translateNumericDayToString(day: number) {
  const days = [
    'sunday',
    'monday',
    'tuesday',
    'wednesday',
    'thursday',
    'friday',
    'saturday',
  ] as const;
  return days[day];
}


// Opening hours will be fetched from API, but for now, let's assume these opening hours:
const opening_hours: {
  monday: {
    from: '0900',
    to: '2200',
  },
}

const OpenNow: React.FC<Business> = ({ opening_hours }) => {
  const time = useRef<TextInput>(null);
  const claculateIsOpen = useCallback(() => {
    if (!opening_hours) return; // If the business has not provided opening hours, we don't know whether they are open or not.

    const currentDateTime = new Date();
    const currentDayIndex = currentDateTime.getDay();
    const currentDay: keyof typeof opening_hours = translateNumericDayToString(currentDayIndex);
    const currentHour = currentDateTime.getHours();
    const currentMinute = currentDateTime.getMinutes();
    const currentTime = `${currentHour}${currentMinute}`;

    const openSlotsArray = [];
    for (const [key, value] of Object.entries(opening_hours[currentDay]))) {
      if (key === 'from') {
        const currentlyClosed = value > parseInt(currentTime, 10);
        openSlotsArray.push(currentlyClosed); // If true, then it's closed
      }
      if (key === 'to') {
        const currentlyClosed = value < parseInt(currentTime, 10);
        openSlotsArray.push(currentlyClosed); // If true, then it's closed
      }
    }
    if (openSlotsArray.includes(true)) {
      // Using setNativeProps to update the value of a <TextInput> because there is no title value for a <Text> component, and to avoid re-rendering, I'm not updating a state and printing it inside a <Text> component.
      time.current?.setNativeProps({ text: 'Closed', color: 'grey' });
    } else {
      time.current?.setNativeProps({ text: 'Open', color: 'green' });
    }
  }, [opening_hours]);
  claculateIsOpen();

  useEffect(() => {
    const secondsTimer = setInterval(() => {
      claculateIsOpen();
    }, 1000);
    return () => clearInterval(secondsTimer);
  }, [claculateIsOpen]);

  return (
    <View style={{ flex: 1 }}>
      <TextInput ref={time} editable={false} />
    </View>
  );
};

export default OpenNow;

尽管此组件有效,但仅在一秒钟后打印“打开”或“关闭”。

但是总的来说,我非常感谢对此代码的一些专家审查。我相信它可以被优化。我对React Native还是比较陌生,所以如果您有改进的建议,请分享。

真的很感谢您的帮助。

0 个答案:

没有答案