From 74f0738a62c55205b05b426162e8fb4babc1446e Mon Sep 17 00:00:00 2001 From: Aleksey Troynikov Date: Thu, 21 Dec 2023 16:33:35 +0300 Subject: [PATCH] refactor(CopyToClipboard): replaced class component by functional component --- .../CopyToClipboard/CopyToClipboard.tsx | 90 ++++++------------- src/components/CopyToClipboard/types.ts | 11 ++- 2 files changed, 32 insertions(+), 69 deletions(-) diff --git a/src/components/CopyToClipboard/CopyToClipboard.tsx b/src/components/CopyToClipboard/CopyToClipboard.tsx index 59cbf37cdc..6e52843f62 100644 --- a/src/components/CopyToClipboard/CopyToClipboard.tsx +++ b/src/components/CopyToClipboard/CopyToClipboard.tsx @@ -2,77 +2,41 @@ import React from 'react'; import ReactCopyToClipboard from 'react-copy-to-clipboard'; -import type { - CopyToClipboardBaseProps, - CopyToClipboardContent, - CopyToClipboardStatus, -} from './types'; +import type {CopyToClipboardProps, CopyToClipboardStatus} from './types'; -interface CopyToClipboardGeneralProps extends CopyToClipboardBaseProps { - children: CopyToClipboardContent; -} - -interface CopyToClipboardDefaultProps { - timeout: number; -} +const INITIAL_STATUS: CopyToClipboardStatus = 'pending'; -interface CopyToClipboardInnerProps - extends CopyToClipboardGeneralProps, - CopyToClipboardDefaultProps {} +export function CopyToClipboard(props: CopyToClipboardProps) { + const {children, text, options, timeout, onCopy} = props; -export interface CopyToClipboardProps - extends CopyToClipboardGeneralProps, - Partial {} + const [status, setStatus] = React.useState(INITIAL_STATUS); -interface CopyToClipboardState { - status: CopyToClipboardStatus; -} + const timerIdRef = React.useRef(); -export class CopyToClipboard extends React.Component< - CopyToClipboardInnerProps, - CopyToClipboardState -> { - static INITIAL_STATUS: CopyToClipboardStatus = 'pending'; + const content = React.useMemo(() => children(status), [children, status]); - state: CopyToClipboardState = { - status: CopyToClipboard.INITIAL_STATUS, - }; + const handleCopy = React.useCallback['onCopy']>( + (copyText, result) => { + setStatus(result ? 'success' : 'error'); + window.clearTimeout(timerIdRef.current); + timerIdRef.current = window.setTimeout(() => { + setStatus(INITIAL_STATUS); + timerIdRef.current = undefined; + }, timeout); + onCopy?.(copyText, result); + }, + [onCopy, timeout], + ); - private timerId?: number; + React.useEffect(() => () => window.clearTimeout(timerIdRef.current), []); - componentWillUnmount() { - clearTimeout(this.timerId); + if (!React.isValidElement(content)) { + throw new Error('Content must be a valid react element'); } - render() { - const {children, text, options} = this.props; - const {status} = this.state; - const content = children(status); - - if (!React.isValidElement(content)) { - throw new Error('Content must be a valid react element'); - } - - return ( - - {content} - - ); - } - - private handleCopy = (text: string, result: boolean) => { - const {timeout, onCopy} = this.props; - - this.setState({ - status: result ? 'success' : 'error', - }); - - clearTimeout(this.timerId); - this.timerId = window.setTimeout(() => { - this.setState({status: CopyToClipboard.INITIAL_STATUS}); - this.timerId = undefined; - }, timeout); - - onCopy?.(text, result); - }; + return ( + + {content} + + ); } diff --git a/src/components/CopyToClipboard/types.ts b/src/components/CopyToClipboard/types.ts index 4f998f7633..8927f62c9a 100644 --- a/src/components/CopyToClipboard/types.ts +++ b/src/components/CopyToClipboard/types.ts @@ -1,3 +1,5 @@ +import type React from 'react'; + import type ReactCopyToClipboard from 'react-copy-to-clipboard'; export type CopyToClipboardStatus = 'pending' | 'success' | 'error'; @@ -6,13 +8,10 @@ export type OnCopyHandler = (text: string, result: boolean) => void; export type CopyToClipboardContent = (status: CopyToClipboardStatus) => React.ReactElement; -export interface CopyToClipboardBaseProps { - /** Text to copy */ +export interface CopyToClipboardProps { text: string; - - /** Handler that would be invoked after copy to clipboard */ + timeout: number; + children: CopyToClipboardContent; onCopy?: OnCopyHandler; - - /** copy-to-clipboard options */ options?: ReactCopyToClipboard.Options; }