| import isEqual from 'lodash/isEqual'; | |
| import { useEffect, useRef, useState } from 'react'; | |
| export const useSetModalState = () => { | |
| const [visible, setVisible] = useState(false); | |
| const showModal = () => { | |
| setVisible(true); | |
| }; | |
| const hideModal = () => { | |
| setVisible(false); | |
| }; | |
| return { visible, showModal, hideModal }; | |
| }; | |
| export const useDeepCompareEffect = ( | |
| effect: React.EffectCallback, | |
| deps: React.DependencyList, | |
| ) => { | |
| const ref = useRef<React.DependencyList>(); | |
| let callback: ReturnType<React.EffectCallback> = () => {}; | |
| if (!isEqual(deps, ref.current)) { | |
| callback = effect(); | |
| ref.current = deps; | |
| } | |
| useEffect(() => { | |
| return () => { | |
| if (callback) { | |
| callback(); | |
| } | |
| }; | |
| }, []); | |
| }; | |
| export interface UseDynamicSVGImportOptions { | |
| onCompleted?: ( | |
| name: string, | |
| SvgIcon: React.FC<React.SVGProps<SVGSVGElement>> | undefined, | |
| ) => void; | |
| onError?: (err: Error) => void; | |
| } | |
| export function useDynamicSVGImport( | |
| name: string, | |
| options: UseDynamicSVGImportOptions = {}, | |
| ) { | |
| const ImportedIconRef = useRef<React.FC<React.SVGProps<SVGSVGElement>>>(); | |
| const [loading, setLoading] = useState(false); | |
| const [error, setError] = useState<Error>(); | |
| const { onCompleted, onError } = options; | |
| useEffect(() => { | |
| setLoading(true); | |
| const importIcon = async (): Promise<void> => { | |
| try { | |
| ImportedIconRef.current = (await import(name)).ReactComponent; | |
| onCompleted?.(name, ImportedIconRef.current); | |
| } catch (err: any) { | |
| onError?.(err); | |
| setError(err); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| importIcon(); | |
| }, [name, onCompleted, onError]); | |
| return { error, loading, SvgIcon: ImportedIconRef.current }; | |
| } | |