menu

Questions & Answers

What's the best practice - Headless UI Modals inside loop - React.js

I've just started my React journey a month ago, I got a question (I migth sound stupid), It's in my head from past 2-3 days.

The Question:

Suppose we have a table with list of Super-heros, and each row contains a Edit button, clicking that opens a Headless UI Modal with a Edit form.

Now my concern is, Should I put the Modal inside of the Super-heros loop, or create the Modal along with a State outside of the loop. And we'll update the state from within the loop to open/close the outside modal. Which would be considered as good practice and also good for performance.

My Thought:

I think how Headless UI's modals work like: whenever the modal get's opened then only it get's rendered to the DOM. So having the Modal components inside of loop shouldn't matter.


I don't need help with the code, just giving some explanation is really appreciated.

Thank you.

Answers(1) :

create the dialog component in different file :

import { useState } from 'react'
import { Dialog } from '@headlessui/react'

export default function MyDialog(props) {
  const {isOpen, selectedItem, handleClose} = props
  return (
    <Dialog open={isOpen} onClose={handleClose}>
      <Dialog.Panel>
       
        ... YOUR UPDATE FORM 

        <button onClick={() => {
         // YOUR UPDATE LOGIC 
         //NOTE : YOU HAVE THE SELECTED ITEM
         handleClose();
        }}>Update</button>
        <button onClick={handleClose}>Cancel</button>
      </Dialog.Panel>
    </Dialog>
  )
}

now form the page in which you will display your table :

import MyDialog from '../'
const [selectedItem, setSelectedItem] = useState({});
const [openDialog, setOpenDialog] = useState(false); 

// your logic 

return(<>
<table>
<tr>
<th>Hero name</th>
<th>Edit Hero</th>
</tr>
{
heros.map((hero) => (
<tr key={hero.id}>
<td>hero.name</td>
<td><button onClick={()=>{
setSelectedItem(hero)
setOpenDialog(true);
}}>edit</button></td>
</tr>
))
}
</table>

<MyDialog   
isOpen={openDialog}
selectedItem={selectedItem}
handleClose={() => {
setOpenDialog(false);
setSelectedItem({})
}}
/>
</>)

ech time you click the button the page component will re-render with selectedItem = the_selected_item and isOpen = true so MyDialog component is open and recive the selectedItem you update your item there inside it then you close it