У меня есть проект, и этот проект содержит несколько интерфейсов, и среди этих интерфейсов есть интерфейс для загрузки изображения, и проблема в значке удаления. При нажатии на него появляется модальное окно, но элемент удаляется до появления модального окна.
Как я могу решить проблему?
этот файл отображает список инструкций, содержащих загрузку изображения
import '../../../styles/input/index.scss';
import '../../../styles/dropzone/index.scss';
import { Button, Col, message, Modal, Row, Spin, Upload, UploadFile } from 'antd';
import { FunctionComponent, useCallback, useRef, useState } from 'react';
import { motion, useAnimation } from 'framer-motion';
import { defaultTranstion } from '../../../constants/framer';
import { Controller } from 'react-hook-form';
import FromElemnetWrapper from '../form-element-wrapper';
import { Delete, UploadCloud } from 'react-feather';
import { getBase64 } from '../../../utils/get-base64';
import _ from 'lodash';
import config from '../../../api/nuclearMedicineApi/config';
import { FormattedMessage } from 'react-intl';
import BasicModal from '../modal';
import { UploadOutlined } from '@ant-design/icons';
import axios from 'axios';
import { IFormError } from '../general-form-containner';
interface DropzoneProps {
name: string;
control: any;
rules?: any;
label: string;
disabled?: boolean;
multiple?: boolean;
accept?: string;
refType?: number;
defaultFileList?: any;
onRemove?: any;
customRequest?: (option: any) => void;
onProgress?: any;
}
const Dropzone: FunctionComponent<DropzoneProps> = ({
name,
control,
rules,
label,
disabled,
multiple,
accept,
refType,
defaultFileList,
onRemove,
customRequest,
onProgress
}) => {
const focusController = useAnimation();
const errorController = useAnimation();
const [previewVisible, setpreviewVisible] = useState(false);
const [previewImage, setpreviewImage] = useState('');
const handleCancel = () => setpreviewVisible(false);
const handlePreview = async (file: any) => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj);
}
setpreviewImage(file?.preview ?? file.url);
setpreviewVisible(true);
};
const [isModalOpen, setIsModalOpen] = useState(false);
const [errors, setErrors] = useState<IFormError[]>([]);
const [visibleModal, setVisibleModal] = useState(false);
const [removePromise, setRemovePromise] = useState();
const [deleteVisible, setdeleteVisible] = useState<boolean>(false);
const onDeleteHandle = () => {
setdeleteVisible(false);
};
const deletehandleCancel = () => {
setdeleteVisible(false);
};
let resolvePromiseRef = useRef<((value: boolean) => void) | undefined>();
// let resolvePromiseRef = useRef<HTMLInputElement | null>(null)
const handleRemove = useCallback(() =>{
const promise = new Promise(resolve => {
resolvePromiseRef.current = resolve
});
setVisibleModal(true);
return promise;
}, [])
const handleOkModalRemove = useCallback(() => {
if (resolvePromiseRef.current) {
resolvePromiseRef.current(true)
}
}, [removePromise]);
const handleCancelModalRemove = useCallback(() => {
if (resolvePromiseRef.current) {
resolvePromiseRef.current(false);
setVisibleModal(false)
}
}, [removePromise]);
return (
<>
<FromElemnetWrapper
focusController = {focusController}
errorController = {errorController}
label = {label}
required = {rules.required?.value}
>
<Controller
control = {control}
name = {name}
rules = {rules}
render = {({
field: { onChange, onBlur, value, name, ref },
fieldState: { invalid, error },
}) => {
if (invalid) {
errorController.start({ scale: 80 });
} else {
errorController.start(
{ scale: 0 },
{ ease: defaultTranstion.ease.reverse() },
);
}
return (
<div
onBlur = {() => {
onBlur();
focusController.start({ scale: 0 });
}}
onFocus = {() => {
focusController.start({ scale: 80 });
}}
className='relative'
>
<div className='upload-container'>
<form
className='dropzone needsclick'
id='demo-upload'
action='/upload'
>
{/* <> */}
<Upload
action = {`${config.baseUrl}api/services/app/Attachment/Upload`}
headers = {config.headers}
ref = {ref}
multiple = {multiple}
disabled = {disabled}
data = {{ RefType: refType }}
listType='picture'
fileList = {value}
id = {name}
accept = {accept}
onPreview = {handlePreview}
onRemove = {handleRemove}
iconRender = {
() => {
return <Spin style = {{ marginBottom: '12px', paddingBottom: '12px' }}></Spin>
}
}
progress = {{
strokeWidth: 3,
strokeColor: {
"0%": "#f0f",
"100%": "#ff0"
},
style: { top: 12 }
}}
beforeUpload = {
(file) => {
console.info({ file });
return true
}
}
// onProgress= {(event: any) => (event.loaded / event.total) * 100}
// onChange = {(e) =>
// onChange(e.fileList)
// }
// onChange = {(response) => {
// console.info('response: ', response);
// if (response.file.status !== 'uploading') {
// console.info(response.file, response.fileList);
// }
// if (response.file.status === 'done') {
// message.success(`${response.file.name}
// file uploaded successfully`);
// } else if (response.file.status === 'error') {
// message.error(`${response.file.name}
// file upload failed.`);
// }
// else if (response.file.status === 'removed') {
// message.error(`${response.file.name}
// file upload removed.`);
// }
// }}
>
<div className='upload-button'>
<div className='wrapper'>
<motion.div
className='fas fa-angle-double-up'
whileHover = {{
y: [
0, -2, 2,
0,
],
transition: {
duration: 1.5,
ease: 'easeInOut',
yoyo: Infinity,
},
}}
>
<UploadCloud
style = {{
margin: '.2rem',
display:
'inline-block',
}}
color='white'
size = {20}
/>
Upload
</motion.div>
</div>
</div>
</Upload>
{/*
<Modal
title = "Are you sure?"
visible = {visibleModal}
onOk = {handleOkModalRemove}
onCancel = {handleCancelModalRemove}
/> */}
<BasicModal
header = {
<>
<FormattedMessage id = {'confirmdeletion'} />
</>
}
headerType='error'
content = {
<>
<Row>
<Col span = {8} offset = {4}>
<Button
type='primary'
className='savebtn'
onClick = {onDeleteHandle}
style = {{
cursor:
Object.keys(errors).length !==
0
? 'not-allowed'
: 'pointer',
}}
>
<FormattedMessage id = {'affirmation'} />
</Button>
</Col>
<Col span = {8} offset = {4}>
<Button
type='default'
className='savebtn'
onClick = {deletehandleCancel}
style = {{
cursor:
Object.keys(errors).length !==
0
? 'not-allowed'
: 'pointer',
}}
>
<FormattedMessage id = {'cancel'} />
</Button>
</Col>
</Row>
</>
}
isOpen = {visibleModal}
footer = {false}
width='35vw'
handleCancel = {handleCancelModalRemove}
handleOk = {handleOkModalRemove}
/>
{/* {_.isEmpty(value) && (
<div className='dz-message needsclick'>
<FormattedMessage id='dropfileshere' />
</div>
)} */}
<BasicModal
isOpen = {previewVisible}
header = {<FormattedMessage id = "Preview image" />}
footer = {false}
handleCancel = {handleCancel}
content = {<img
alt='example'
style = {{ width: '100%' }}
src = {previewImage}
/>}
/>
{/* </> */}
</form>
</div>
{invalid && (
<p className='form-element-error'>
{error?.message}
</p>
)}
</div>
);
}}
/>
</FromElemnetWrapper>
</>
);
};
export default Dropzone;
https://ant.design/components/upload
onRemove - функция обратного вызова будет выполняться при нажатии кнопки удаления файла, событие удаления будет предотвращено, если возвращаемое значение равно false или обещание, которое разрешается (false) или отклоняется
Вы должны вернуть обещание, которое разрешается как ложное или возвращает ложное
Вы должны вернуть обещание, поэтому, прежде всего, вам нужна ссылка или состояние для хранения функции разрешения этого обещания, чтобы вы могли вызывать ее в модальном режиме.
const resolvePromiseRef = useRef<((value: boolean) => void) | undefined>();
Затем вам нужно будет назначить функцию resolve
ссылке и вернуть обещание.
Теперь onRemove
буду ждать, пока ваше обещание разрешится
const handleRemove = () =>{
const promise = new Promise(resolve => {
resolvePromiseRef.current = resolve
});
setVisibleModal(true);
return promise;
}
Теперь ваши обработчики функций
const handleOkModalRemove = useCallback(() => {
if (resolvePromiseRef.current) {
resolvePromiseRef.current(true)
}
}, [removePromise]);
const handleCancelModalRemove = useCallback(() => {
if (resolvePromiseRef.current) {
resolvePromiseRef.current(false)
}
}, [removePromise]);
Вы также можете использовать состояние, но я рекомендую ref, потому что оно не перерисовывает компонент при изменении.
я не могу удалить элемент из интерфейса после нажатия OK @Konrad