最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - HTML Dialog Element in React.js - Stack Overflow

programmeradmin0浏览0评论

Im remaking one of my older projects using react+TS+Tailwind and I decided to use element for modal instead of creating classic modal element - I choose it due to accessibility.

However I ran into some issues. Currently when I can set this ponent to open when it uses open attribute, but then it opens as dialog and not as modal. I do not know where to call .showModal() method and on what exactly to open it as a modal (heh this seems to be easier for me to do in vanilla js :P)

Thats my Modal ponent

interface Props {
    showModal: HandleModal
    edit: (id: number, value: string) => void
    closeModal: React.Dispatch<React.SetStateAction<HandleModal>>
}

const Modal = ({ showModal, edit, closeModal }: Props) => {
    let modalContent = (
        <div className=''>
            <p>Please input a correct task in the input field</p>
            <Button click={() => closeModal({ show: false })}>Close</Button>
        </div>
    )

    let modalTitle = 'Error'
    return (
        <dialog aria-modal='true' open={showModal.show} className='dialog'>
            <div className=''>
                <h1>{modalTitle}</h1>
            </div>
            {modalContent}
        </dialog>
    )
}
export default Modal

And thats my App file

function App() {
    const [toDos, setToDos] = useState(DummyToDos)
    const [showModal, setShowModal] = useState<HandleModal>({
        show: false,
    })

    const addToDo = (todo: Todo) => {
        setToDos(prevState => {
            return [todo, ...prevState]
        })
    }

    const editToDo = (id: number, value: string) => {
        const editedToDos = [...toDos].map(todo => {
            if (todo.id === id) {
                todo.text = value
            }
            return todo
        })
        setToDos(editedToDos)
        setShowModal({
            show: false,
        })
    }

    const deleteToDo = (id: number) => {
        const newToDos = toDos.filter(todo => todo.id !== id)
        setToDos(newToDos)
    }
    const pleteToDo = (id: number) => {
        const pletedToDos = [...toDos].map(todo => {
            if (todo.id === id) {
                todoplete = !todoplete
            }
            return todo
        })
        setToDos(pletedToDos)
    }

    return (
        <div className='mx-auto flex h-96 w-10/12 flex-col items-center text-center'>
            <Header add={addToDo} showModal={setShowModal} />
            <ToDoList items={toDos} edit={setShowModal} plete={pleteToDo} del={deleteToDo} />

            <Modal edit={editToDo} showModal={showModal} closeModal={setShowModal}/>
        </div>
    )
}

export default App

I can open this ponent chaning open attribute to true but it opens as dialog and not modal. I've tried setting aria-modal to true to force it to open as modal - sadly it doesnt work. I do not know where and on what exactly should I call .showModal() method

Im remaking one of my older projects using react+TS+Tailwind and I decided to use element for modal instead of creating classic modal element - I choose it due to accessibility.

However I ran into some issues. Currently when I can set this ponent to open when it uses open attribute, but then it opens as dialog and not as modal. I do not know where to call .showModal() method and on what exactly to open it as a modal (heh this seems to be easier for me to do in vanilla js :P)

Thats my Modal ponent

interface Props {
    showModal: HandleModal
    edit: (id: number, value: string) => void
    closeModal: React.Dispatch<React.SetStateAction<HandleModal>>
}

const Modal = ({ showModal, edit, closeModal }: Props) => {
    let modalContent = (
        <div className=''>
            <p>Please input a correct task in the input field</p>
            <Button click={() => closeModal({ show: false })}>Close</Button>
        </div>
    )

    let modalTitle = 'Error'
    return (
        <dialog aria-modal='true' open={showModal.show} className='dialog'>
            <div className=''>
                <h1>{modalTitle}</h1>
            </div>
            {modalContent}
        </dialog>
    )
}
export default Modal

And thats my App file

function App() {
    const [toDos, setToDos] = useState(DummyToDos)
    const [showModal, setShowModal] = useState<HandleModal>({
        show: false,
    })

    const addToDo = (todo: Todo) => {
        setToDos(prevState => {
            return [todo, ...prevState]
        })
    }

    const editToDo = (id: number, value: string) => {
        const editedToDos = [...toDos].map(todo => {
            if (todo.id === id) {
                todo.text = value
            }
            return todo
        })
        setToDos(editedToDos)
        setShowModal({
            show: false,
        })
    }

    const deleteToDo = (id: number) => {
        const newToDos = toDos.filter(todo => todo.id !== id)
        setToDos(newToDos)
    }
    const pleteToDo = (id: number) => {
        const pletedToDos = [...toDos].map(todo => {
            if (todo.id === id) {
                todo.plete = !todo.plete
            }
            return todo
        })
        setToDos(pletedToDos)
    }

    return (
        <div className='mx-auto flex h-96 w-10/12 flex-col items-center text-center'>
            <Header add={addToDo} showModal={setShowModal} />
            <ToDoList items={toDos} edit={setShowModal} plete={pleteToDo} del={deleteToDo} />

            <Modal edit={editToDo} showModal={showModal} closeModal={setShowModal}/>
        </div>
    )
}

export default App

I can open this ponent chaning open attribute to true but it opens as dialog and not modal. I've tried setting aria-modal to true to force it to open as modal - sadly it doesnt work. I do not know where and on what exactly should I call .showModal() method

Share Improve this question asked Jun 27, 2023 at 17:07 Jakub KamińskiJakub Kamiński 531 silver badge3 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

You need to have a ref to that dialog element and close or open dialog depending on your showModal.show state

const dialogRef = useRef<HTMLDialogElement>(null)

useEffect(() => {
    if (dialogRef.current?.open && !showModal.show) {
      dialogRef.current?.close()
    } else if (!dialogRef.current?.open && showModal.show) {
      dialogRef.current?.showModal()
    }
}, [showModal.show])

// ...

return (
   <dialog ref={dialogRef}>
    ...
   </dialog>
)
发布评论

评论列表(0)

  1. 暂无评论