React Open Modal Window on Click in Another Component

How to open Modal from another component in hooks?

You want to control the show/hide from the parent component

const HomePage = () => {
const [showLogin, setShowLogin] = useState(false);
return (
<>
<button onClick={() => setShowLogin(true)}>Open Modal</button>
<LoginModal show={showLogin} close={() => setShowLogin(false)} />
</>
);
};
<Modal
show={props.show}
cancel={props.close}
...

Here is a working example:

https://codesandbox.io/s/nice-euclid-d0dw0

How to show Modal after clicking a button in another component in React?

Your parent component seems ok to me. It would say the issue comes from how you handle the button interaction and props in the child.

I would start by trying something like that :

Parent:

   import NewAreaModal from "./NewAreaModal";

function GestioneAree() {

const [aree, setAree] = useState([]);
const [show, setShow] = useState(false);

useEffect(() => {
axios.get("http://localhost:8080/aree/all").then((res) => {
setAree(res.data);
console.log(res.data);
});
}, []);

const showModal = () => {
setShow(true);
}

return (
<div className="bg-white rounded-lg">
<div className="px-4 py-5 sm:px-6 rounded">
<div className="-ml-4 -mt-2 flex items-center justify-between flex-wrap sm:flex-nowrap">
<div className="ml-4 mt-2">
<h3 className="text-lg leading-6 font-medium text-gray-900">Aree nel Sistema</h3>
</div>
<div className="ml-4 mt-2 flex-shrink-0">
<Button type="button" decoration="primary" text="Crea Nuova Area" onClick={showModal}/>
</div>
</div>
</div>
<div className="flex flex-col">
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<div className="shadow overflow-hidden border-t border-gray-200 sm:rounded-lg">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Toponimo
</th>
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Territorio
</th>
<th scope="col" className="relative px-6 py-3">
<span className="sr-only">Edit</span>
</th>
</tr>
</thead>
<tbody>
{aree.map((area) => (
<tr key={area.idArea} className="bg-white border-b">
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{area.toponimo}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{area.territorio.nome}</td>
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button type="button" className="text-green-600 hover:text-green-900" >
Modifica
</button>
</td>
</tr>
))}
</tbody>
</table>
<NewAreaModal show={show} setShow={(bool) => setShow(bool) />
</div>
</div>
</div>
</div>
</div>
);
}

export default GestioneAree;

Child :

import React, { useState, useRef, Fragment } from "react";
import { Dialog, Transition } from "@headlessui/react";
import Button from "../../../components/Button";

function NewAreaModal({show, setShow}) {

const cancelButtonRef = useRef(null);


return (
<Transition.Root show={show}>
<Dialog as="div" className="relative z-10" initialFocus={cancelButtonRef} onClose={setOpen}>
<Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0" enterTo="opacity-100" leave="ease-in duration-200" leaveFrom="opacity-100" leaveTo="opacity-0">
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed z-10 inset-0 overflow-y-auto">
<div className="flex items-end sm:items-center justify-center min-h-full p-4 text-center sm:p-0">
<Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enterTo="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<Dialog.Panel className="relative bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:max-w-lg sm:w-full">
<div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
{
// Form here
}
</div>
<div className="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<Button type="button" text="Crea Area" decoration="primary" otherCSS={"w-full justify-center sm:ml-3 sm:w-auto sm:text-sm"} onClick={() => setShow(false)}/>
<Button type="button" text="Annulla" decoration="secondary" otherCSS={"w-full justify-center sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"} onClick={() => setShow(false)} ref={cancelButtonRef}/>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}

export default NewAreaModal;

How to change state of modal from a different component in react

Use props. You should manage the Modal's open state in Products and pass the value to Modal as a prop whenever a product is clicked. Add a onClose prop to Modal and create a function to call setOpen(false) in Product whenever the modal is closed.
Also, include <Modal> somewhere in Product's render() method, otherwise you will never see it.

In Products, it would be something like this:

export default function Products() {
const [open, setOpen] = useState(false);
//...
return (
//...
// somewhere in the code you set a onClick event to run setOpen(true)
<Modal open={open} onClose={() => setOpen(false)}>
//...
)
}

Then in Modal:

export default function Modal(props) {
const {open, onClose} = props;

return (
<Transition.Root show={open} as={Fragment}>
//...
<button
type='button'
className='inline-flex justify-center w-full rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:text-sm'
onClick={() => onClose(false)}
>
//...
)
}

How can I open a rect-bootstrap modal dialog from another Component

From what I understand, you want to share the state of show between the Dashboard and SignInButton, as only one modal can be open at the time in the application.

You should handle the show state, handleShow function and handleClose function in the top component, which, in this case, is SignedInButton. Then, you should pass show boolean and handleClose function as props down to the child component, in this case Dashboard.

SignedInButton

function SignedInButton() {
const [show, setShow] = useState(false);
const handleShow = () => setShow(true);
const handleClose = () => setShow(false);

return (
<div>
<Button className="button is-large" onClick={handleShow}>
<span className="icon is-medium">
<i className="fas fa-user" />
</span>
</Button>
<Dashboard show={show} onClose={handleClose}/>
</div>
);
}
// ...

Dashboard

const Dashboard = props => {
const { show, onClose } = props;

return (
<div>
<Modal show={show} onHide={onClose} centered>
<Modal.Header closeButton>
<Modal.Title>User Profile</Modal.Title>
</Modal.Header>
<Modal.Body>
<ProfilePageAuthenticated />
<ProfilePageAnonymous />
<LinkAccounts />
<SummaryPage />
<ContributePage />
<Offline>
<div
style={{
marginTop: 40,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'red',
}}
>
It appears you don't have an active Internet connection!
</div>
</Offline>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={onClose}>
Close
</Button>
</Modal.Footer>
</Modal>
</div>
);
};

I have my modal component in a different file and I'm trying to open it from another component

you are calling the toggleTicketModal function when the TicketModal renders,call it like this

<button onClick={()=>toggleTicketModal()}>close</button>

this will do.



Related Topics



Leave a reply



Submit