在依赖项更改后反应 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]);
只要 deliveryDate
和 deliveryTime
发生变化,效果就会重新运行,并且仅在不是第一次 运行 时才显示警报。
我会在 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);
});
我正在为我的应用程序使用 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]);
只要 deliveryDate
和 deliveryTime
发生变化,效果就会重新运行,并且仅在不是第一次 运行 时才显示警报。
我会在 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);
});