在依赖项更改后反应 useEffect() 警报一次

React useEffect() alert once after dependences change

我正在为我的应用程序使用 Typescript。我在数据库中有两组数据,一组是date,一组是time。两者都需要字符串。

我在用户选择日期时发出了一个 POST 请求,该时间将为用户选择。我为用户选择的时间何时结束制作了一个辅助函数,在这种情况下,我会在前端向他们展示一个显示

的警报

"Your selected time expired!"

显示该警报后。我强行清除了交货时间。我的逻辑工作正常。每当我访问屏幕时,它总是提醒屏幕不利于 UI 和用户体验。但我知道 useEffect() 会在我访问该屏幕时产生影响,因为依赖项发生了变化。有什么方法可以在时间到期时只显示一次警报,然后每当用户访问时他们都看不到警报?

PS: I am thinking should I do with something with my helper function

这是我的示例代码,我也在code-sandbox

中分享了我的代码
import "./styles.css";
import { isToday } from "date-fns";
import React, { useEffect } from "react";

export const isEmptyString = (value: string): boolean =>
  !value || value.trim().length === 0;

export const isTimeWindowExpired = (date: string, time: string) => {
  if (isEmptyString(date)) {
    return undefined;
  } else {
    const [yyyy, mm, dd]: Array<string> = date.split("-");
    const d: Date = new Date();
    d.setFullYear(+yyyy);
    d.setMonth(+mm - 1);
    d.setDate(+dd);
    if (isToday(d)) {
      const matcher = d.toTimeString().match(/(\d{2}:\d{2}):.*/);
      if (matcher) {
        const [currentLocalTime] = matcher.slice(1);

        const [startTime, endTime] = time.split("-");

        return currentLocalTime >= startTime && currentLocalTime <= endTime;
      }
    }
    return false;
  }
};

const deliveryDate = "2021-06-18";
const deliveryTime = "07:12-07:13";

export default function App() {
  useEffect(() => {
    const isExpired = isTimeWindowExpired(deliveryDate, deliveryTime);
    if (!isExpired) {
      alert("delivery_time_expired");
    }
  }, []);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Edit to see some magic happen!</h2>
    </div>
  );
}

您可以使用 ref 来跟踪效果是否是第一次触发。

const firstTimeRef = useRef<boolean>(true)
useEffect(() => {
  const isExpired = isTimeWindowExpired(deliveryDate, deliveryTime);
  if (!isExpired && !firstTimeRef.current) {
    alert("delivery_time_expired");
  }
  firstTimeRef.current = false
}, [deliveryDate, deliveryTime]);

只要 deliveryDatedeliveryTime 发生变化,效果就会重新运行,并且仅在不是第一次 运行 时才显示警报。

我会在 localStorage 中设置一个过期值。读取组件挂载时的值,检查过期时间。如果过期已过,则显示警报并清除 localStorage,否则在组件保持安装状态时为警报设置超时。如果组件在 到期之前 卸载,请不要忘记在 useEffect 挂钩清理函数中清除超时。

在 component/effect 外部,只是将过期值存入本地存储。我正在使用 luxon 库进行日期时间管理。

import { DateTime } from "luxon";

const EXPIRATION_KEY = "expiration";

const deliveryDate = "2021-06-17";
const deliveryTime = "22:45";

let timer: number;
const expiration = DateTime.fromISO(deliveryDate + "T" + deliveryTime);
window.localStorage.setItem(EXPIRATION_KEY, expiration.toISO());

在组件中。

useEffect(() => {
  const expirationTrigger = () => {
    alert("delivery_time_expired");
    window.localStorage.removeItem(EXPIRATION_KEY);
  };

  const expirationString = window.localStorage.getItem(EXPIRATION_KEY);
  if (expirationString) {
    const expiration = DateTime.fromISO(expirationString);
    if (expiration.diffNow() < 0) {
      expirationTrigger();
    } else {
      timer = setTimeout(expirationTrigger, expiration.diffNow().milliseconds);
    }
  }

  // effect cleanup to clear timeout when component unmounts
  return () => clearTimeout(timer);
});