在模态中确认删除评论时,React 不渲染警报

问题描述 投票:0回答:1

上下文:交互式评论部分CRUD应用程序

删除评论时,用户单击“删除”按钮,该按钮将打开一个模式,要求他们确认删除。该部分(模式打开/关闭和删除评论)工作正常。

我想添加的是一旦用户确认删除并且评论被删除后的警报/闪光通知。我能够在更新评论时实现这一点,但是当使用完全相同的方法进行删除时,由于某种原因,警报没有呈现。

我有一种感觉,这与该组件使用模态有关,但我无法弄清楚到底是什么在阻塞。

我尝试过的:

  • 直接在
    DeleteConfirmationModal
    中设置警报状态和 showAlert 函数(而不是从父组件传递它)
  • {alert.show && <Alert {...alert} showAlert={showAlert} />}
    置于
    Modal
    内或置于
    article
  • 强制模式保持打开状态(出于调试目的)
  • 为警报
    aside
    元素提供高 z 索引
  • 使用 React 门户在模式的 DOM 层次结构之外渲染警报

下面是我的代码。如果有人能帮我解决这个问题,我将不胜感激。

const UserActionButtons = ({ comment, isEditing, isMobile, isReply, isCurrentUser, onDelete, editComment, handleClickReply}: UserActionButtonsProps) => {
    const [isDeleteModalOpen, setDeleteModalOpen] = useState<boolean>(false)

    const handleOpenConfirmationModal = (): void => {
        setDeleteModalOpen(true)
    }

    const handleCloseConfirmationModal = (): void => {
        setDeleteModalOpen(false)
    }

    return (
        <>
            {isCurrentUser ?
                (<div className={`${isEditing && isMobile ? 'hidden' : 'cta-button'}`}>
                    <div className='flex items-center fill-primary-red-soft hover:fill-primary-red-pale   text-primary-red-soft hover:text-primary-red-pale  '>
                        <DeleteIcon />
                        <p className="font-medium mr-4"
                            onClick={() => handleOpenConfirmationModal()}
                        >  Delete</p>
                    </div>
                    <DeleteConfirmationModal
                        isOpen={isDeleteModalOpen}
                        onDelete={onDelete}
                        onCancel={handleCloseConfirmationModal}
                        comment={comment}
                        isReply={isReply}
                    />
                    <div className='flex items-center cta-button-blue'>
                        <EditIcon />
                        <p className="font-medium"
                            onClick={editComment}
                        >  Edit</p>
                    </div>
                </div>
                ) : !isEditing &&
                (<div className='cta-button cta-button-blue'>
                    <ReplyIcon />
                    <p className="font-medium"
                        onClick={handleClickReply}
                    >  Reply</p>
                </div>)}
        </>
    )
}
const DeleteConfirmationModal = ({
    isOpen,
    comment,
    isReply,
    onCancel,
    onDelete
}: DeleteConfirmationModalProps) => {
    const { id } = comment
    const [alert, setAlert] = useState<AlertInterface>({ show: false, type: '', text: '' })

    const showAlert = (show = false, type = '', text = ''): void => {
        setAlert({ show, type, text })
    }

    const deleteComment = (id: number, deletedComment?: MessageMeta): void => {
        onDelete(id, deletedComment)
        showAlert(true, 'success', 'Comment deleted!')
        // console.log(alert.show)
    }

    useEffect(() => {
        console.log(alert)
    }, [alert])

    return (
        <>
            {alert.show && <Alert {...alert} showAlert={showAlert} />}
            <Modal isOpen={isOpen}>
                <article className='flex flex-col gap-y-4'>
                    <h4 className='font-medium text-xl text-neutral-blue-dark'>Delete comment</h4>
                    <p className='text-neutral-blue-grayish'>Are you sure you want to delete this comment? This will remove the comment and can't be undone.</p>
                    <div className='flex gap-x-2 justify-between'>
                        <button className='bg-neutral-blue-grayish text-white font-medium px-4 sm:px-8 py-3 uppercase rounded-lg border-none w-6/12'
                            onClick={onCancel}>No, cancel</button>
                        <button className='bg-primary-red-soft text-white font-medium px-4 sm:px-8 py-3 uppercase rounded-lg border-none w-6/12'
                            onClick={() => deleteComment(id, isReply ? comment : undefined)}
                        >Yes, delete</button>
                    </div>
                </article>
            </Modal >
        </>
    )
}
const Alert = ({
    type,
    text,
    showAlert
}: AlertProps) => {

    console.log('alert renders')

    useEffect(() => {
        const timeout = setTimeout(() => {
            showAlert()
        }, 3000)
        return () => clearTimeout(timeout)
    }, [])

    return (
        <aside className={`${type === 'success' ? 'bg-primary-green-success' : 'bg-primary-red-soft'} text-white fixed bottom-5 right-5 p-4 z-50`}>{text}</aside>
    )
}
const Modal = ({
    isOpen,
    children
}: ModalProps) => {
    const [isModalOpen, setModalOpen] = useState(isOpen)
    const modalRef = useRef<HTMLDialogElement | null>(null)

    useEffect(() => {
        setModalOpen(isOpen)
    }, [isOpen])

    useEffect(() => {
        const modalElement = modalRef.current

        if (modalElement) {
            if (isModalOpen) {
                modalElement.showModal()
            } else {
                modalElement.close()
            }
        }
    }, [isModalOpen])

    return (
        <dialog ref={modalRef}
            className={'p-4 sm:p-6 rounded-lg min-w-20 max-w-xs sm:max-w-sm cursor-default'}>
            {children}
        </dialog>
    )
}
reactjs modal-dialog alert
1个回答
0
投票

我实际上找到了我上面分享的代码中没有的解决方案 基本上因为我递归地渲染评论,所以我还需要将

showAlert
属性传递给 Comment 组件本身

我还将状态提升到最高父级

 {comment.replies?.length !== 0 ? (
            <div className='flex w-full'>
                <div className='w-0.5 bg-neutral-gray-light md:ml-12'></div>
                <div className='pl-6 md:pl-12 max-w-full flex-grow'>
                    {comment.replies?.map((reply) =>
                    (<Comment
                        key={reply.id}
                        comment={reply}
                        currentUser={currentUser}
                        commentList={commentList}
                        onReply={onReply}
                        onEdit={onEdit}
                        onDelete={onDelete}
                        onScoreChange={onScoreChange}
                        showAlert={showAlert}
                    />))}
                </div>
            </div>) : null}
© www.soinside.com 2019 - 2024. All rights reserved.