admin管理员组

文章数量:1293369

I have this two ponents:

import React, { useState, useEffect } from "react";
import axios from "axios";
import Button from "../../../ponents/Button";
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} />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
}

export default GestioneAree;

and

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

function NewAreaModal() {
    const [open, setOpen] = useState(true);

    const cancelButtonRef = useRef(null);

    return (
        <Transition.Root show={open}>
            <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={() => setOpen(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={() => setOpen(false)} ref={cancelButtonRef}/>
                                </div>
                            </Dialog.Panel>
                        </Transition.Child>
                    </div>
                </div>
            </Dialog>
        </Transition.Root>
    );
}

export default NewAreaModal;

What I want to do is opening the ponent NewAreaModal.js when I'm clicking the Crea Nuova Area button... what is wrong with my code?

I have tried many ways but it dosen't work. For example, I tried to pass a prop to NewAreaModal called show and then I putted this variable inside useState in const [open, setOpen] = useState(show) but the <Transition> ponent says that is missing the show prop even if I passed a boolean variable...

This code is missing some functions for the unication with the backend because I just started!

I'm practicing React since 2 months so I don't have a lot of experience...

Thank you guys for the patience!

I have this two ponents:

import React, { useState, useEffect } from "react";
import axios from "axios";
import Button from "../../../ponents/Button";
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} />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
}

export default GestioneAree;

and

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

function NewAreaModal() {
    const [open, setOpen] = useState(true);

    const cancelButtonRef = useRef(null);

    return (
        <Transition.Root show={open}>
            <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={() => setOpen(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={() => setOpen(false)} ref={cancelButtonRef}/>
                                </div>
                            </Dialog.Panel>
                        </Transition.Child>
                    </div>
                </div>
            </Dialog>
        </Transition.Root>
    );
}

export default NewAreaModal;

What I want to do is opening the ponent NewAreaModal.js when I'm clicking the Crea Nuova Area button... what is wrong with my code?

I have tried many ways but it dosen't work. For example, I tried to pass a prop to NewAreaModal called show and then I putted this variable inside useState in const [open, setOpen] = useState(show) but the <Transition> ponent says that is missing the show prop even if I passed a boolean variable...

This code is missing some functions for the unication with the backend because I just started!

I'm practicing React since 2 months so I don't have a lot of experience...

Thank you guys for the patience!

Share edited Jun 1, 2022 at 10:46 BOGDAN DONICI asked Jun 1, 2022 at 9:47 BOGDAN DONICIBOGDAN DONICI 1291 gold badge1 silver badge10 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

Your parent ponent seems ok to me. It would say the issue es 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 "../../../ponents/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;

I have tried many ways but it dosen't work. For example, I tried to pass a prop to NewAreaModal called show and then I putted this variable inside useState in const [open, setOpen] = useState(show) but the <Transition> ponent says that is missing the show prop even if I passed a boolean variable...

Passing in the show prop is the right idea, but you are missing a few things, and overplicating in some other areas.

The code in the GestioneAree ponent looks correct to me - you have a show state variable that you pass in to NewAreaModal, and set this to true when the button is clicked to open the modal. This is all correct. All you need to do is to have NewAreaModal use that to determine whether to show the ponent's contents or not.

To do that you need to first have NewAreaModal accept show as a prop:

function NewAreaModal({ show }) {
  // ponent code
}

This show prop will then be the only thing that controls whether the modal is open or not. So you don't need, or want, any state here. So remove this line:

const [open, setOpen] = useState(true);

and instead use the show prop where you were using open before - in particular pass it to the Transition.Root, which is ponent you don't show but I assume this is what will actually show or hide the contents:

<Transition.Root show={show}>

That's essentially it, but there's another important way you will have to change your code. Your modal ponent appears to have a button inside it to close the modal. That would work when you had the open (or show) property in state, as you could have the button set that state to false. That doesn't work directly when show is a prop instead.

But there's an easy fix - to simply have your modal ponent accept a function that closes the modal.

You already have an openModal function defined in your parent ponent:

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

and you can do something similar to make a "closeModal" function:

const closeModal = () => {
    setShow(false);
}

Then you can pass this function in as a prop to NewAreaModal:

<NewAreaModal show={show} closeModal={closeModal}/>

Finally, NewAreaModal needs to accept this prop:

function NewAreaModal({ show, closeModal }) {
  // ponent code
}

and call it when the close button is clicked, by replacing onClick={() => setOpen(false)} by onClick={closeModal} for each button where you have this.

(Note that if you are using NewAreaModal elsewhere you will need to ensure this closeModal prop is passed in each time it is used.)

本文标签: javascriptHow to show Modal after clicking a button in another component in ReactStack Overflow