1- import { ReactNode , useState } from 'react' ;
1+ import { ReactNode , useEffect , useState } from 'react' ;
2+ import { useWatch } from 'react-hook-form' ;
23
34import { Button , Popconfirm , Space } from 'antd' ;
45import clsx from 'clsx' ;
56import deepEqual from 'fast-deep-equal' ;
67import { AnimatePresence } from 'framer-motion' ;
78
9+ import { UseCustomUseFormReturn } from '~/hooks/useCustomForm' ;
10+
811import { SaveButtonStyled } from './styled' ;
912
1013export interface SaveButtonProps {
11- formik : any ;
14+ form : UseCustomUseFormReturn < any , any > ;
1215 defaultValues : any ;
1316 className ?: string ;
1417 confirmText ?: ReactNode ;
1518 useConfirm ?: boolean ;
16- reset ?: boolean ;
1719}
1820
1921const animation = {
@@ -41,37 +43,59 @@ const animation = {
4143 } ,
4244} ;
4345
46+ let timeoutHandle : NodeJS . Timeout ;
47+
4448const SaveButton = ( {
49+ form,
4550 className,
4651 defaultValues,
47- formik,
4852 confirmText,
4953 useConfirm = false ,
50- reset,
5154} : SaveButtonProps ) => {
55+ const [ invalid , setInvalid ] = useState ( false ) ;
5256 const [ confirmVisible , setConfirmVisible ] = useState ( false ) ;
5357 const [ loading , setLoading ] = useState ( false ) ;
5458
55- const isEqual = deepEqual ( defaultValues , formik . values ) ;
59+ const values = useWatch ( {
60+ control : form . control ,
61+ } ) ;
62+
63+ const isEqual = deepEqual ( defaultValues , values ) ;
5664
5765 const handleSave = async ( ) => {
5866 setLoading ( true ) ;
59- await formik . submitForm ( ) ;
67+
68+ const valid = await form . submit ( ) ;
69+
70+ if ( ! valid ) {
71+ setInvalid ( true ) ;
72+ }
73+
6074 setLoading ( false ) ;
6175 } ;
6276
77+ useEffect ( ( ) => {
78+ clearTimeout ( timeoutHandle ) ;
79+
80+ if ( invalid ) {
81+ timeoutHandle = setTimeout ( ( ) => {
82+ setInvalid ( false ) ;
83+ } , 1000 ) ;
84+ }
85+ } , [ invalid ] ) ;
86+
6387 return (
6488 < AnimatePresence >
6589 { ! isEqual && (
66- < SaveButtonStyled className = { clsx ( 'SaveButton' , className ) } key = "SaveButton" { ...animation } >
90+ < SaveButtonStyled
91+ className = { clsx ( 'SaveButton' , className , { invalid } ) }
92+ key = "SaveButton"
93+ { ...animation }
94+ >
6795 < span > 저장하지 않은 변경 사항이 있어요!</ span >
6896
6997 < Space >
70- < Button
71- className = "cancel"
72- onClick = { ( ) => ( reset ? formik . handleReset ( ) : formik . setValues ( defaultValues ) ) }
73- disabled = { loading }
74- >
98+ < Button className = "cancel" disabled = { loading } onClick = { ( ) => form . reset ( defaultValues ) } >
7599 되돌리기
76100 </ Button >
77101
@@ -80,8 +104,8 @@ const SaveButton = ({
80104 okText = "저장"
81105 cancelText = "취소"
82106 placement = "topRight"
83- visible = { confirmVisible }
84- onVisibleChange = { ( visible : boolean ) => {
107+ open = { confirmVisible }
108+ onOpenChange = { ( visible : boolean ) => {
85109 if ( useConfirm ) {
86110 setConfirmVisible ( visible ) ;
87111 }
@@ -95,7 +119,7 @@ const SaveButton = ({
95119 className = "save"
96120 type = "primary"
97121 loading = { loading }
98- onClick = { useConfirm ? ( ) => { } : handleSave }
122+ onClick = { useConfirm ? undefined : handleSave }
99123 >
100124 변경사항 저장하기
101125 </ Button >
0 commit comments