我正在尝试为React创建一个简单的通知提供程序,如果你点击通知,它会非常好地工作。但是,当使用从父级传递到子级的"finished"函数时,子级的超时函数似乎使用了一个旧的状态。几乎就像timeout快照数据,或者setState在超时完成后排队一样。可以使用timeout吗,还是我需要重新考虑一下汽车消失的事
import styles from "@styles/Notification.module.scss";
import React, { createContext, useState } from "react";
import NotificationCard from "@components/Notifications/Notification";
import { uuid4 } from "@sentry/utils";
export interface NotificationInterface {
notifications: Notification[];
info(notification: Notification): void;
success(notification: Notification): void;
warning(notification: Notification): void;
error(notification: Notification): void;
}
export interface Notification {
id?: string;
message: string;
level?: NotificationLevel;
timeout?: number;
delay?: number;
}
export enum NotificationLevel {
INFO = "info",
SUCCESS = "success",
WARNING = "warning",
ERROR = "error"
}
export const NotificationContext = createContext<NotificationInterface>({} as NotificationInterface);
export const NotificationProvider = ({ children }: { children?: JSX.Element }) => {
const [notifications, setNotifications] = useState<Notification[]>([]);
const createNotification = (notification: Notification): Notification => {
return {
id: uuid4(),
level: notification.level || NotificationLevel.INFO,
message: notification.message || "",
timeout: notification.timeout || 5000,
delay: notification.delay || 0
};
};
const info = (notification: Notification) => {
setNotifications([...notifications, createNotification({ ...notification, level: NotificationLevel.INFO })]);
};
const success = (notification: Notification) => {
setNotifications([...notifications, createNotification({ ...notification, level: NotificationLevel.SUCCESS })]);
};
const warning = (notification: Notification) => {
setNotifications([...notifications, createNotification({ ...notification, level: NotificationLevel.WARNING })]);
};
const error = (notification: Notification) => {
setNotifications([...notifications, createNotification({ ...notification, level: NotificationLevel.ERROR })]);
};
const finished = (notification: Notification) => {
setNotifications(notifications.filter((n) => n.id !== notification.id));
};
return (
<NotificationContext.Provider
value={{
notifications,
info,
success,
warning,
error
}}
>
<div className={styles.notificationContainer}>
{notifications.map((notification) => (
<NotificationCard key={notification.id} notification={notification} onFinished={(n) => finished(n)} />
))}
</div>
{children}
</NotificationContext.Provider>
);
};
import styles from "@styles/Notification.module.scss";
import { Notification } from "@utils/notificationProvider";
import { useEffect, useState } from "react";
const NotificationCard = ({
notification,
onFinished
}: {
notification: Notification;
onFinished?: (notification: Notification) => void;
}) => {
const [isOpen, setIsOpen] = useState(true);
const close = () => {
setIsOpen(false);
setTimeout(() => {
if (onFinished) {
onFinished(notification);
}
}, 500);
};
useEffect(() => {
const timeout = setTimeout(() => {
close();
}, notification.timeout);
return () => {
clearTimeout(timeout);
};
}, []);
return (
<div onClick={() => close()} className={isOpen ? styles.notificationCard : styles.notificationCardClosed}>
{notification.message}
</div>
);
};
export default NotificationCard;
1条答案
按热度按时间42fyovps1#
当使用异步代码时,(但我建议几乎总是使用它)。当使用旧状态设置你的状态时,使用回调而不是值。因为状态的值在重新呈现后会改变,但在回调属性中,i是立即改变的。
示例:
而不是这个
用这个
这样,您就可以始终使用当前数据