如何从反应中的不同组件更改模态状态
How to change state of modal from a different component in react
我正在学习 React,但被卡住了。我正在使用 TailwindUI 模式,我希望它在单击产品组件中的产品时弹出。当在产品组件中单击某些内容时,如何将模式的状态从 false 更改为 true。澄清一下,模态组件在产品组件中被调用,但模态的初始状态设置为 false。
import Modal from "./Modal";
const products = [
{
id: 1,
name: "Organize Basic Set (Walnut)",
price: "9",
rating: 5,
reviewCount: 38,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-01.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 2,
name: "Organize Pen Holder",
price: "",
rating: 5,
reviewCount: 18,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-02.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 3,
name: "Organize Sticky Note Holder",
price: "",
rating: 5,
reviewCount: 14,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-03.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 4,
name: "Organize Phone Holder",
price: "",
rating: 4,
reviewCount: 21,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-04.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 5,
name: "Organize Basic Set (Walnut)",
price: "9",
rating: 5,
reviewCount: 38,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-01.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 6,
name: "Organize Pen Holder",
price: "",
rating: 5,
reviewCount: 18,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-02.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 7,
name: "Organize Sticky Note Holder",
price: "",
rating: 5,
reviewCount: 14,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-03.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 8,
name: "Organize Phone Holder",
price: "",
rating: 4,
reviewCount: 21,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-04.jpg",
imageAlt: "TODO",
href: "#",
},
// More products...
];
function classNames(...classes) {
return classes.filter(Boolean).join(" ");
}
export default function Products() {
return (
<div className='bg-white' id='product-line'>
<div className='max-w-7xl mx-auto overflow-hidden sm:px-6 lg:px-8'>
<h2 className='sr-only'>Products</h2>
<h1 className='text-3xl font-extrabold text-blue-800 mt-10 sm:mt-20 mb-1 ml-4'>
Product Line
</h1>
<div className='-mx-px border-l border-gray-200 grid grid-cols-2 sm:mx-0 md:grid-cols-3 lg:grid-cols-4'>
{products.map((product) => (
<div
key={product.id}
className='group relative p-4 border-r border-b border-gray-200 sm:p-6'
>
<div className='rounded-lg overflow-hidden bg-gray-200 aspect-w-1 aspect-h-1 group-hover:opacity-75'>
<img
src={product.imageSrc}
alt={product.imageAlt}
className='w-full h-full object-center object-cover'
/>
</div>
<div className='pt-10 pb-4 text-center'>
<h3 className='text-sm font-medium text-gray-500'>
<a href={product.href}>
<span aria-hidden='true' className='absolute inset-0' />
{product.name}
</a>
</h3>
</div>
</div>
))}
</div>
</div>
</div>
);
}
import { Fragment, useState } from "react";
import { Dialog, Transition } from "@headlessui/react";
import { CheckIcon } from "@heroicons/react/outline";
export default function Modal() {
const [open, setOpen] = useState(false);
return (
<Transition.Root show={open} as={Fragment}>
<Dialog
as='div'
className='fixed z-10 inset-0 overflow-y-auto'
onClose={setOpen}
>
<div className='flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0'>
<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'
>
<Dialog.Overlay className='fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity' />
</Transition.Child>
{/* This element is to trick the browser into centering the modal contents. */}
<span
className='hidden sm:inline-block sm:align-middle sm:h-screen'
aria-hidden='true'
>
​
</span>
<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'
>
<div className='inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6'>
<div>
<div className='mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-green-100'>
<CheckIcon
className='h-6 w-6 text-green-600'
aria-hidden='true'
/>
</div>
<div className='mt-3 text-center sm:mt-5'>
<Dialog.Title
as='h3'
className='text-lg leading-6 font-medium text-gray-900'
>
Payment successful
</Dialog.Title>
<div className='mt-2'>
<p className='text-sm text-gray-500'>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Consequatur amet labore.
</p>
</div>
</div>
</div>
<div className='mt-5 sm:mt-6'>
<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={() => setOpen(false)}
>
Go back to dashboard
</button>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition.Root>
);
}
使用props
。您应该在 Products
中管理模态框的打开状态,并在单击产品时将值作为 prop
传递给 Modal
。将 onClose
属性添加到 Modal
并创建一个函数以在关闭模态时在 Product
中调用 setOpen(false)
。
另外,在Product
的render()
方法中的某处包含<Modal>
,否则你将永远看不到它。
在Products
中会是这样的:
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)}>
//...
)
}
然后在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)}
>
//...
)
}
我正在学习 React,但被卡住了。我正在使用 TailwindUI 模式,我希望它在单击产品组件中的产品时弹出。当在产品组件中单击某些内容时,如何将模式的状态从 false 更改为 true。澄清一下,模态组件在产品组件中被调用,但模态的初始状态设置为 false。
import Modal from "./Modal";
const products = [
{
id: 1,
name: "Organize Basic Set (Walnut)",
price: "9",
rating: 5,
reviewCount: 38,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-01.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 2,
name: "Organize Pen Holder",
price: "",
rating: 5,
reviewCount: 18,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-02.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 3,
name: "Organize Sticky Note Holder",
price: "",
rating: 5,
reviewCount: 14,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-03.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 4,
name: "Organize Phone Holder",
price: "",
rating: 4,
reviewCount: 21,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-04.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 5,
name: "Organize Basic Set (Walnut)",
price: "9",
rating: 5,
reviewCount: 38,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-01.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 6,
name: "Organize Pen Holder",
price: "",
rating: 5,
reviewCount: 18,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-02.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 7,
name: "Organize Sticky Note Holder",
price: "",
rating: 5,
reviewCount: 14,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-03.jpg",
imageAlt: "TODO",
href: "#",
},
{
id: 8,
name: "Organize Phone Holder",
price: "",
rating: 4,
reviewCount: 21,
imageSrc:
"https://tailwindui.com/img/ecommerce-images/category-page-05-image-card-04.jpg",
imageAlt: "TODO",
href: "#",
},
// More products...
];
function classNames(...classes) {
return classes.filter(Boolean).join(" ");
}
export default function Products() {
return (
<div className='bg-white' id='product-line'>
<div className='max-w-7xl mx-auto overflow-hidden sm:px-6 lg:px-8'>
<h2 className='sr-only'>Products</h2>
<h1 className='text-3xl font-extrabold text-blue-800 mt-10 sm:mt-20 mb-1 ml-4'>
Product Line
</h1>
<div className='-mx-px border-l border-gray-200 grid grid-cols-2 sm:mx-0 md:grid-cols-3 lg:grid-cols-4'>
{products.map((product) => (
<div
key={product.id}
className='group relative p-4 border-r border-b border-gray-200 sm:p-6'
>
<div className='rounded-lg overflow-hidden bg-gray-200 aspect-w-1 aspect-h-1 group-hover:opacity-75'>
<img
src={product.imageSrc}
alt={product.imageAlt}
className='w-full h-full object-center object-cover'
/>
</div>
<div className='pt-10 pb-4 text-center'>
<h3 className='text-sm font-medium text-gray-500'>
<a href={product.href}>
<span aria-hidden='true' className='absolute inset-0' />
{product.name}
</a>
</h3>
</div>
</div>
))}
</div>
</div>
</div>
);
}
import { Fragment, useState } from "react";
import { Dialog, Transition } from "@headlessui/react";
import { CheckIcon } from "@heroicons/react/outline";
export default function Modal() {
const [open, setOpen] = useState(false);
return (
<Transition.Root show={open} as={Fragment}>
<Dialog
as='div'
className='fixed z-10 inset-0 overflow-y-auto'
onClose={setOpen}
>
<div className='flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0'>
<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'
>
<Dialog.Overlay className='fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity' />
</Transition.Child>
{/* This element is to trick the browser into centering the modal contents. */}
<span
className='hidden sm:inline-block sm:align-middle sm:h-screen'
aria-hidden='true'
>
​
</span>
<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'
>
<div className='inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6'>
<div>
<div className='mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-green-100'>
<CheckIcon
className='h-6 w-6 text-green-600'
aria-hidden='true'
/>
</div>
<div className='mt-3 text-center sm:mt-5'>
<Dialog.Title
as='h3'
className='text-lg leading-6 font-medium text-gray-900'
>
Payment successful
</Dialog.Title>
<div className='mt-2'>
<p className='text-sm text-gray-500'>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Consequatur amet labore.
</p>
</div>
</div>
</div>
<div className='mt-5 sm:mt-6'>
<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={() => setOpen(false)}
>
Go back to dashboard
</button>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition.Root>
);
}
使用props
。您应该在 Products
中管理模态框的打开状态,并在单击产品时将值作为 prop
传递给 Modal
。将 onClose
属性添加到 Modal
并创建一个函数以在关闭模态时在 Product
中调用 setOpen(false)
。
另外,在Product
的render()
方法中的某处包含<Modal>
,否则你将永远看不到它。
在Products
中会是这样的:
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)}>
//...
)
}
然后在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)}
>
//...
)
}