依赖改变后反应 useEffect() 警报一次

时间:2021-06-18 04:42:28

标签: reactjs alert use-effect

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

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

<块引用>

“您选择的时间已过期!”

显示该警报后。我强行清除交货时间。我的逻辑工作正常。每当我访问屏幕时,它总是提醒屏幕,这对 UI 和 UX 不利。但我知道 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>
  );
}

2 个答案:

答案 0 :(得分:0)

您可以使用 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 更改时,效果都会重新运行,并且仅在第一次未运行时才显示警报。

答案 1 :(得分:0)

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

在组件/效果之外,只是将过期值放入本地存储。我正在使用 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);
});

Edit react-useeffect-alert-once-after-dependences-change