react FC toast 组件
2021-01-15 本文已影响0人
vavid
v1
import React, { useState, useEffect } from 'react';
import classNames from 'classnames';
import Backdrop from './Backdrop';
import ReactDOM from 'react-dom';
import './ToastV2.scss';
interface ToastProps {
className?: string;
content: string;
time?: number;
}
const block = 'toast';
const Toast = (props: ToastProps) => {
const [visiable, setVisiable] = useState(true);
useEffect(() => {
const timerId = setTimeout(() => {
setVisiable(false);
}, props.time);
return () => {
clearTimeout(timerId);
};
}, [props.time]);
return (
<Backdrop
className={classNames(props.className, `${block}__mask`, {
[`${block}__toast--show`]: visiable,
})}
>
<div className={`${block}__info`}>{props.content}</div>
</Backdrop>
);
};
export const ShowToast = (props: ToastProps) => {
return ReactDOM.render(
<Toast content={props.content} time={props.time || 3000} />,
document.querySelector('#toast')
);
};
v2
import React, { useRef, useState, useEffect } from 'react';
import classNames from 'classnames';
import Backdrop from './Backdrop';
import './ToastV2.scss';
interface ToastProps {
className?: string;
content: string;
time?: number;
}
const block = 'toast';
const Toast = (props: ToastProps) => {
const { className, content, time } = props;
const [visiable, setVisiable] = useState(false);
const timerID: any = useRef(0);
useEffect(() => {
const show = () => {
if (timerID.current) return;
if (content) {
setVisiable(true);
timerID.current = setTimeout(() => {
setVisiable(false);
}, time);
}
};
const hide = () => {
clearTimeout(timerID.current);
setVisiable(false); //
// 预留toast消失之后的回调
};
show();
return () => {
hide();
};
}, [content, time]);
if (!visiable) return null;
return (
<Backdrop
className={classNames(className, `${block}__mask`, {
[`${block}__toast--show`]: visiable,
})}
>
<div className={`${block}__info`}>{content}</div>
</Backdrop>
);
};
export default Toast;
css
$block: 'toast';
.#{$block}__mask {
display: none;
background: transparent;
}
.#{$block}__toast--show {
display: block;
}
.#{$block}__info {
position: absolute;
top: 50%;
left: 50%;
padding: 10px 20px;
transform: translate(-50%, -50%);
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.6);
color: #fff;
}