You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NotificationsTransition.tsx 1.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import React, { ReactElement, useEffect, useState } from 'react';
  2. export const NotificationsTransitionContext = React.createContext({
  3. unmounting: new Map<string, TimeoutType | null>()
  4. });
  5. type TimeoutType = ReturnType<typeof setTimeout>;
  6. const NotificationsTransition = ({ children }: { children: ReactElement[]; }) => {
  7. const [ childrenToRender, setChildrenToRender ] = useState(children);
  8. const [ timeoutIds, setTimeoutIds ] = useState(new Map<string, TimeoutType | null>());
  9. useEffect(() => {
  10. const toUnmount = childrenToRender.filter(child =>
  11. children.findIndex(c => c.props.uid === child.props.uid) === -1) ?? [];
  12. const toMount = children?.filter(child =>
  13. childrenToRender.findIndex(c => c.props.uid === child.props.uid) === -1) ?? [];
  14. if (toUnmount.length > 0) {
  15. const ids = new Map(timeoutIds);
  16. toUnmount.forEach(child => {
  17. const timeoutId = setTimeout(() => {
  18. timeoutIds.set(child.props.uid, null);
  19. setTimeoutIds(timeoutIds);
  20. }, 250);
  21. ids.set(child.props.uid, timeoutId);
  22. });
  23. setTimeoutIds(ids);
  24. }
  25. setChildrenToRender(toMount.concat(childrenToRender));
  26. }, [ children ]);
  27. useEffect(() => {
  28. const toRemove: string[] = [];
  29. timeoutIds.forEach((value, key) => {
  30. if (value === null) {
  31. toRemove.push(key);
  32. timeoutIds.delete(key);
  33. }
  34. });
  35. toRemove.length > 0 && setChildrenToRender(childrenToRender.filter(child =>
  36. toRemove.findIndex(id => child.props.uid === id) === -1));
  37. }, [ timeoutIds ]);
  38. return (
  39. <NotificationsTransitionContext.Provider value = {{ unmounting: timeoutIds }}>
  40. {childrenToRender}
  41. </NotificationsTransitionContext.Provider>
  42. );
  43. };
  44. export default NotificationsTransition;