mh-rn-component
Version:
142 lines (134 loc) • 3.55 kB
Flow
import React, {
createContext,
MutableRefObject,
useState,
useMemo,
useContext,
useCallback
} from 'react'
import Toast, { Props } from './index'
import { ToastType, VisibleToastsType, ToastContextType, ToastList } from "./types"
// 创建一个createContext
const ToastContext = createContext<ToastContextType>({
toastList: {},
visibleToasts: {},
setToast: () => { },
hideToast: () => { },
hideAll: () => { },
loading: () => { }
});
// 组件调用Context
const CustomToast = () => {
const { toastList, visibleToasts, hideToast } = useContext(ToastContext)
const toastListIds = () => {
return Object.keys(visibleToasts)
}
return (<>
{
toastListIds().map((id) => {
return (<Toast key={id} onChange={() => hideToast(id)} show={visibleToasts[id]} {...toastList[id]}></Toast>)
})
}
</>)
}
// 组件调用Context
export const ToastProvider = ({ children }: { children: any }) => {
const [toastList, setToastList] = useState<ToastList>({})
const [visibleToasts, setVisibleToasts] = useState<VisibleToastsType>({});
const toastIndex = React.useRef(7000);
const hideToast = useCallback(
(id: any) => {
setVisibleToasts((prev) => {
return { ...prev, [id]: false }
})
}, [setVisibleToasts])
const hideAll = useCallback(() => {
setVisibleToasts({})
}, [setVisibleToasts])
const setToast = useCallback(
(props: ToastType): number => {
const {
id = toastIndex.current++,
...rest
} = props
setToastList((prev) => {
return {
...prev, [id]: {
id,
...rest
}
}
})
setVisibleToasts((prev) => {
return { ...prev, [id]: true }
})
return id
},
[toastList, visibleToasts, hideToast]
)
const loading = useCallback(
(props: ToastType): number => {
const {
id = toastIndex.current++,
...rest
} = props
setToastList((prev) => {
return {
...prev, [id]: {
id,
icon: "loading1",
duration: 0,
loading: true,
...rest
}
}
})
setVisibleToasts((prev) => {
return { ...prev, [id]: true }
})
return id
},
[toastList, visibleToasts, hideToast]
)
const contextValue = useMemo(() => {
return {
toastList,
visibleToasts,
setToast,
hideToast,
hideAll,
loading
}
}, [toastList, visibleToasts, setToast, hideToast, hideAll, loading])
return (
<ToastContext.Provider value={contextValue}>
{children}
<CustomToast></CustomToast>
</ToastContext.Provider>
)
}
export const useToast = () => {
const { setToast, hideToast, hideAll, loading } = React.useContext(
ToastContext
);
const toast = useMemo(
() => ({
show: setToast,
close: hideToast,
closeAll: hideAll,
loading: loading
}),
[setToast, hideToast, hideAll, loading]
);
return toast;
}
//!这部分和ref相关的
export type IToastService = ReturnType<typeof useToast>;
export const ToastRef = React.createRef<IToastService>() as MutableRefObject<IToastService>;
export const _Toast: IToastService = {
show: (props: Props) => ToastRef.current?.show(props),
close: (id: any) => ToastRef.current?.close(id),
closeAll: () => ToastRef.current?.closeAll(),
loading: (props: Props) => ToastRef.current?.show(props),
// isActive: (id: any) => ToastRef.current?.isActive(id),
};