cyb/src/features/adviser/context.tsx

import React, { useCallback, useContext, useMemo, useState } from 'react';
import { Props as AdviserProps } from './Adviser/Adviser';

type ContextType = {
  setAdviser: (content: AdviserProps['children'], color?: AdviserProps['color']) => void;
  setAdviserNew: (
    id: string,
    content: AdviserProps['children'],
    color?: AdviserProps['color']
  ) => void;
  content: AdviserProps['children'];
  color?: AdviserProps['color'];
  isOpen: boolean;
  setIsOpen: (isOpen: boolean) => void;
};

const AdviserContext = React.createContext<ContextType>({
  content: '',

  /*
   * @deprecated use setAdviserNew
   */
  setAdviser: () => {},
  setAdviserNew: () => {},
  isOpen: false,
  setIsOpen: () => {},
});

const AdviserContext2 = React.createContext<ContextType['setAdviserNew']>({});

export function useAdviser() {
  const context = React.useContext(AdviserContext);
  if (!context) {
    throw new Error('useAdviser must be used within a AdviserProvider');
  }
  return context;
}

export function useSetAdviser() {
  const setAdviser = useContext(AdviserContext2);

  return { setAdviser };
}

// enum Priority {
//   HIGH,
// }

type StateItem = {
  id: string;
  content: AdviserProps['children'];
  color?: AdviserProps['color'];
  isPriority: boolean;
};

type State = StateItem[];

const NO_ID = 'NO_ID';

function AdviserProvider({ children }: { children: React.ReactNode }) {
  const [isOpen, setIsOpen] = useState<ContextType['isOpen']>(false);

  const [state, setState] = useState<State>([]);

  const handleSetAdviser = useCallback((id: string, content, color, priority) => {
    setState((prev) => {
      const newState = prev.filter((item) => item.id !== id);

      const n = [...newState];

      if (content) {
        n.push({
          id,
          content,
          color,
          isPriority: priority,
        });
      }

      return n;
    });

    setIsOpen(true);
  }, []);

  const handleSetAdviserLegacy = useCallback(
    (content, color) => {
      handleSetAdviser(NO_ID, content, color);
    },
    [handleSetAdviser]
  );

  const priorityItem = [...state].reverse().find((item) => item.isPriority);
  const lastItem = priorityItem || state[state.length - 1];

  const { content, color } = lastItem || {};

  const value = useMemo(() => {
    return {
      setAdviser: handleSetAdviserLegacy,
      // need some refactor
      setAdviserNew: handleSetAdviser,
      content,
      color,
      setIsOpen,
      isOpen,
    };
  }, [content, color, isOpen, handleSetAdviser, handleSetAdviserLegacy]);

  return (
    <AdviserContext.Provider value={value}>
      {/* second context to prevent rerenders */}
      <AdviserContext2.Provider value={handleSetAdviser}>{children}</AdviserContext2.Provider>
    </AdviserContext.Provider>
  );
}

export default AdviserProvider;

Synonyms

cyb/src/websockets/context.tsx
pussy-ts/src/websockets/context.tsx
pussy-ts/src/features/adviser/context.tsx

Neighbours