反应通知钩子口吃

发布于 2025-01-10 20:55:10 字数 4173 浏览 0 评论 0 原文

我制作了一个用于简单通知类型系统的钩子。但每当我发送垃圾邮件通知时,它就会开始像窃听/抖动一样。

我将在下面给出一个 gif 示例:

在此处输入图像描述

好的,让我们开始讨论实际的代码本身:

这是我的反应挂钩:

import { useEffect, useState } from "react";

export default () => {
    const [notifications, setNotifications] = useState([]);  
    const addNotification = (notification) => setNotifications([...notifications, notification]);
    const deleteNotification = (id: number) =>
        setNotifications(notifications.filter((m) => m.id !== id));
  
    return { notifications, addNotification, deleteNotification };
};

这是我的通知项

import { useEffect, useState } from "react";
import '../components/App.css'

  interface INotificationItem {
    notification,
    deleteNotification(id: number): void;
  }
  
  export default (props: INotificationItem) => {
    const { deleteNotification, notification } = props;
    const { id } = notification;
  
    const [alive, setAlive] = useState(true);
    const [fadeOut, setFadeOut] = useState(false);

    useEffect(() => {
      const timer = setTimeout(() => setAlive(false), 2000);
      return () => {
        clearTimeout(timer);
      };
    }, []);
  
    useEffect(() => {
      if (!alive) {
        setFadeOut(true)
        setTimeout(() => {
            deleteNotification(id);
        }, 300)
      }
    }, [alive, deleteNotification, id]);

    return (
    <div className={fadeOut ? "notification top-right-out" : "notification top-right-in"}>
    </div>
    );
  };

最后是我的 app.tsx main文件:

import React, { useState } from 'react';
import './App.css'
import useNotificationManager from '../hooks/useNotificationManager';
import NotificationIItem from '../items/NotificationIItem';

const App: React.FC = (props) => {
    const { addNotification, deleteNotification, notifications } = useNotificationManager();
    const [notificationInd, setNotificationInd] = useState(0);

    const addNotification = () => {
      addNotification({ id: notificationInd});
      setNotificationInd(notificationInd + 1);    
    }


    return (
        <>
        <div className="top-right-in" style={{position: 'fixed', boxSizing: 'border-box'}}>
        <div className="column-wrap top-right-in" style={{display: notifications.length > 0 ? 'flex' : 'none', flexDirection: 'column-reverse'}}>
        {notifications.map((notification) => (
            <NotificationIItem
              deleteNotification={deleteNotification}
              notification={notification}
              key={notification.id}
            />
        ))}
        </div>
        </div>
        </>
    )
}

export default App;

CSS:

.column-wrap {
    transition: transform .6s ease-in-out;
    animation: toast-in-right .7s;
}

@keyframes toast-in-right {
    from {
      transform: translateX(100%);
      
    }
    to {
      transform: translateX(0);
    }
}

@keyframes toast-out-right {
    from {
      transform: translateX(0);
      
    }
    to {
      transform: translateX(100%);
    }
}

.notification-container {
    font-size: 14px;
    box-sizing: border-box;
    position: fixed;
}

.top-right-in {
    top: 12px;
    right: 12px;
    transition: transform .6s ease-in-out;
    animation: toast-in-right .5s;
}

.top-right-out {
    top: 12px;
    right: 12px;
    transition: transform .6s ease-in-out;
    animation: toast-out-right .5s;
}

.notification {
    background: #fff;
    transition: .3s ease;
    position: relative;
    pointer-events: auto;
    overflow: hidden;
    margin: 0 0 6px;
    padding: 30px;
    margin-bottom: 15px;
    width: 300px;
    max-height: 100px;
    border-radius: 3px 3px 3px 3px;
    box-shadow: 0 0 10px #999;
    color: #000;
    opacity: .9;
    background-position: 15px;
    background-repeat: no-repeat;
}

我有一种感觉,当它删除通知时,或者当我实际调用它并增加通知索引时,它要么是钩子本身的东西。

不管怎样,我希望有新眼光的人能够看到我可能犯的简单错误。

谢谢,并致以亲切的问候。

I made a hook that i use for a simple notification type system. But whenever I spam the notifications it starts like bugging out/jittering out.

I will give a gif example below:

enter image description here

Okay, so let's get down to the actual code itself:

This is my react hook:

import { useEffect, useState } from "react";

export default () => {
    const [notifications, setNotifications] = useState([]);  
    const addNotification = (notification) => setNotifications([...notifications, notification]);
    const deleteNotification = (id: number) =>
        setNotifications(notifications.filter((m) => m.id !== id));
  
    return { notifications, addNotification, deleteNotification };
};

This is my Notification Item

import { useEffect, useState } from "react";
import '../components/App.css'

  interface INotificationItem {
    notification,
    deleteNotification(id: number): void;
  }
  
  export default (props: INotificationItem) => {
    const { deleteNotification, notification } = props;
    const { id } = notification;
  
    const [alive, setAlive] = useState(true);
    const [fadeOut, setFadeOut] = useState(false);

    useEffect(() => {
      const timer = setTimeout(() => setAlive(false), 2000);
      return () => {
        clearTimeout(timer);
      };
    }, []);
  
    useEffect(() => {
      if (!alive) {
        setFadeOut(true)
        setTimeout(() => {
            deleteNotification(id);
        }, 300)
      }
    }, [alive, deleteNotification, id]);

    return (
    <div className={fadeOut ? "notification top-right-out" : "notification top-right-in"}>
    </div>
    );
  };

And for the last, is my app.tsx main file:

import React, { useState } from 'react';
import './App.css'
import useNotificationManager from '../hooks/useNotificationManager';
import NotificationIItem from '../items/NotificationIItem';

const App: React.FC = (props) => {
    const { addNotification, deleteNotification, notifications } = useNotificationManager();
    const [notificationInd, setNotificationInd] = useState(0);

    const addNotification = () => {
      addNotification({ id: notificationInd});
      setNotificationInd(notificationInd + 1);    
    }


    return (
        <>
        <div className="top-right-in" style={{position: 'fixed', boxSizing: 'border-box'}}>
        <div className="column-wrap top-right-in" style={{display: notifications.length > 0 ? 'flex' : 'none', flexDirection: 'column-reverse'}}>
        {notifications.map((notification) => (
            <NotificationIItem
              deleteNotification={deleteNotification}
              notification={notification}
              key={notification.id}
            />
        ))}
        </div>
        </div>
        </>
    )
}

export default App;

CSS:

.column-wrap {
    transition: transform .6s ease-in-out;
    animation: toast-in-right .7s;
}

@keyframes toast-in-right {
    from {
      transform: translateX(100%);
      
    }
    to {
      transform: translateX(0);
    }
}

@keyframes toast-out-right {
    from {
      transform: translateX(0);
      
    }
    to {
      transform: translateX(100%);
    }
}

.notification-container {
    font-size: 14px;
    box-sizing: border-box;
    position: fixed;
}

.top-right-in {
    top: 12px;
    right: 12px;
    transition: transform .6s ease-in-out;
    animation: toast-in-right .5s;
}

.top-right-out {
    top: 12px;
    right: 12px;
    transition: transform .6s ease-in-out;
    animation: toast-out-right .5s;
}

.notification {
    background: #fff;
    transition: .3s ease;
    position: relative;
    pointer-events: auto;
    overflow: hidden;
    margin: 0 0 6px;
    padding: 30px;
    margin-bottom: 15px;
    width: 300px;
    max-height: 100px;
    border-radius: 3px 3px 3px 3px;
    box-shadow: 0 0 10px #999;
    color: #000;
    opacity: .9;
    background-position: 15px;
    background-repeat: no-repeat;
}

I have a feeling it's either something in the hook itself, when it's deleting the notifications or when I actually call it and increase the notification index.

Anyways, I hope someone with fresh eyes maybe sees the simple mistake i may of done.

Thanks, and kind regards.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

混浊又暗下来 2025-01-17 20:55:10

我没有你的 CSS 来完全重现这个问题,但即使没有它,我也注意到一些奇怪的渲染问题。

然而,通过使用功能状态更新,这些问题似乎已得到彻底解决。

示例:

const useNotificationManager = () => {
  const [notifications, setNotifications] = useState([]);

  const addNotification = (notification) =>
    setNotifications((notifications) => [...notifications, notification]);

  const deleteNotification = (id: number) =>
    setNotifications((notifications) =>
      notifications.filter((m) => m.id !== id)
    );

  return { notifications, addNotification, deleteNotification };
};

Edit react-notiifcation-hook-stuttering

更新

尝试优化这里有一些调整:

  1. 删除 alive 状态并调用删除处理程序来处理删除通知。

    const NotificationItem = (props: INotificationItem) =>; {
      const { 删除通知,通知 } = 道具;
      const { id } = 通知;
    
      const [fadeOut, setFadeOut] = useState(false);
    
      useEffect(() => {
        const handleDelete = () =>; {
          setFadeOut(真);
          setTimeout(() => {
            删除通知(id);
          }, 300);
        };
    
        const 计时器 = setTimeout(handleDelete, 2000);
        返回() => {
          清除超时(计时器);
        };
      }, []);
    
      返回 (
        
    {ID}
    ); };
  2. 使用函数生成id值;删除 notificationInd 状态。

    让 id = 0;
    constgenerateId = () =>; id++;
    

    ...

    const addNotification = () =>; {
      addNotification({ id:generateId() });
    };
    

I don't have your CSS to fully reproduce the issue, but even without it I noticed some odd rendering issues.

They appear to be completely resolved, however, by using functional state updates.

Example:

const useNotificationManager = () => {
  const [notifications, setNotifications] = useState([]);

  const addNotification = (notification) =>
    setNotifications((notifications) => [...notifications, notification]);

  const deleteNotification = (id: number) =>
    setNotifications((notifications) =>
      notifications.filter((m) => m.id !== id)
    );

  return { notifications, addNotification, deleteNotification };
};

Edit react-notiifcation-hook-stuttering

Update

In an attempt to optimize here are a few tweaks:

  1. Remove the alive state and call a delete handler to handle removing the notification.

    const NotificationItem = (props: INotificationItem) => {
      const { deleteNotification, notification } = props;
      const { id } = notification;
    
      const [fadeOut, setFadeOut] = useState(false);
    
      useEffect(() => {
        const handleDelete = () => {
          setFadeOut(true);
          setTimeout(() => {
            deleteNotification(id);
          }, 300);
        };
    
        const timer = setTimeout(handleDelete, 2000);
        return () => {
          clearTimeout(timer);
        };
      }, []);
    
      return (
        <div
          className={
            fadeOut ? "notification top-right-out" : "notification top-right-in"
          }
        >
          {id}
        </div>
      );
    };
    
  2. Use a function to generate id values; remove the notificationInd state.

    let id = 0;
    const generateId = () => id++;
    

    ...

    const addNotification = () => {
      addNotification({ id: generateId() });
    };
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文