Reputation: 103
Issue as stated in topic. Goal is to open a modal, and use item.imdbID to fetch data. As it is now, a modal is opened for every entry in the table, and also the id prop is sent for every entry.
const { toggle, visible } = useModal();
<tbody>
{items.map((item, i) => (
<tr key={i}>
<MTd>{item.Title}</MTd>
<MTd>{item.Year}</MTd>
<MTd>{item.imdbID}</MTd>
<MTd>{item.Type}</MTd>
<MTd><button onClick={toggle}>Detaljer</button>
<DetailedViewModal visible={visible} toggle={toggle} id={item.imdbID} />
</MTd>
</tr>
))}
</tbody>
I know one can do <button onClick={e => testClick(item.imdbID)}>Details</button>
when the function resides in the same file, but unsure on how to handle this with a modal.
The modal is custom made; useModal.js:
const useModal = () => {
const [visible, setVisible] = useState(false);
function toggle() {
setVisible(!visible);
}
return {toggle, visible}
};
Modal.js
const Modal = ({ visible, toggle, body }) => visible ? ReactDOM.createPortal(
<div className="modal">
<div className="modal-pop" role="dialog" aria-modal="true">
<div>{body}</div>
<button type="button" onClick={toggle}>Close</button>
</div>
<div className="modal-overlay"></div>
</div>, document.body
) : null;
DetailedViewModal.js
return (
<>
<Modal visible={visible} toggle={toggle} body={modalBody()} />
</>
)
Any good suggestions to make this work is much appreciated.
Upvotes: 1
Views: 182
Reputation: 202676
You are using a single toggle state to toggle visibility of all the modals.
Store a passed id
property for the modal you want to toggle visibility of.
useModal:
Update to either toggle back to null
if the id matches to close the modal, or to toggle on a new id
. Note: toggle
is a curried function so you don't need to create anonymous callback functions to pass the id
when attaching callback.
const useModal = () => {
const [visibleId, setVisible] = useState(null);
const toggle = id => () => setVisible(visibleId => visibleId === Id ? null : id);
return {toggle, visibleId}
};
Component Code:
Pass item.imdbID
or null
to the toggle
callback handler, check the current item.imdbID
equals the current visibleId
value to set the visibility of the modal.
const { toggle, visibleId } = useModal();
...
<tbody>
{items.map((item, i) => (
<tr key={i}>
<MTd>{item.Title}</MTd>
<MTd>{item.Year}</MTd>
<MTd>{item.imdbID}</MTd>
<MTd>{item.Type}</MTd>
<MTd>
<button
onClick={toggle(item.imdbID)} // <-- pass id to handler to open (or close)
>
Detaljer
</button>
<DetailedViewModal
visible={visibleId === item.imdbID} // <-- check id match for opening modal
toggle={toggle(null)} // <-- pass null to close
body={{ /* ... whatever the body is ... */ }}
/>
</MTd>
</tr>
))}
</tbody>
Upvotes: 1