Closing a modal from a nested modal sub-component

I am facing a query regarding how to close a Modal from within a sub-component of the same Modal itself. Allow me to elaborate on what I am trying to achieve here.

I have developed a Modal that is triggered from a Component to enable users to add a new Client to a database. Given that I intend to add several other elements to the database in a similar manner, I opted to create a generic Modal component and pass another component as a prop to the Modal component - such as a form containing the necessary fields to add a new client.

Below is some code for better understanding:

Table.js

import DataTable from 'react-data-table-component';
import React, { useState } from 'react';
import Modal from './modal';

const Table = (props) => {
  const [showModal, setShowModal] = useState(false);

  return (
    <div id='overview' className="bg-slate-100 h-screen w-full overflow-y-auto">
      <div className='flex justify-end h-20 w-3/4 m-auto'>
        <div className='flex space-x-2 h-full'>
          <button type='button' onClick={() => setShowModal(true)} className='self-center inline-block px-6 py-2.5 bg-green-500 text-white font-medium text-xs leading-tight uppercase rounded shadow-md hover:bg-green-600 hover:shadow-lg focus:bg-green-600 focus:shadow-lg focus:outline-none focus:ring-0 active:bg-green-700 active:shadow-lg transition duration-150 ease-in-out'>Add</button>
        </div>
      </div>
      <div className='w-3/4 m-auto'>
        <DataTable 
          columns={props.columns} 
          data={props.tableData} //This will need to be retrieved from the database
          direction="auto"
          fixedHeaderScrollHeight="300px"
          pagination
          responsive
        />
      </div>
      <Modal onClose={() => setShowModal(false)} show={showModal} title={props.title}>
        {props.modal}
      </Modal>
    </div>
  );
};

export default Table;

Modal.js

import React from 'react';

const Modal = ({ show, onClose, children, title }) => {

  const handleCloseClick = (e) => {
    e.preventDefault();
    onClose();
  };

  return ( show ? (
    <div tabIndex="-1" aria-hidden="true" className="overflow-y-auto fixed inset-0 bg-gray-600 bg-opacity-50 z-50 h-full w-full md:inset-0 md:h-full">
      <div className="relative top-20 p-4 mx-auto w-1/2 h-full md:h-auto">
        <div className="relative bg-white rounded-lg shadow dark:bg-gray-700">
          <button type="button" onClick={handleCloseClick} className="absolute top-3 right-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white">
            <svg aria-hidden="true" className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd"></path></svg>
            <span className="sr-only">Close modal</span>
          </button>
          <div className="py-6 px-6 lg:px-8">
            <h3 className="mb-4 text-xl font-medium text-center text-gray-900 dark:text-white">{title}</h3>
            {children}
          </div>
        </div>
      </div>
    </div> 
  ) : null
  );
};

export default Modal;

ClientForm.js

import { useForm } from 'react-hook-form';
import Input from '../form-components/input';
import Button from '../form-components/button';
import { ValidateVat } from '../../lib/vat';
import { useState } from 'react';

const ClientForm = () => {
  const { register, handleSubmit } = useForm();
  const [client, setClient] = useState(undefined);
  const [street, setStreet] = useState(undefined);
  const [city, setCity] = useState(undefined);
  const [zip, setZip] = useState(undefined);

  const populateVatResult = (vatNumber) => {
    ValidateVat(vatNumber)
      .then(data => {
        setClient(data.company.name);
        setStreet(data.company.address.split('\n')[0]);
        setCity(data.company.address.split('\n')[1].split(' ')[1]);
        setZip(data.company.address.split('\n')[1].split(' ')[0]);
      });
    
  };

  const createClient = async (data) => {
    const res = await fetch('http://localhost:3000/api/customer', {method: 'POST', headers: {
      'Content-Type': 'application/json',
    }, body: JSON.stringify({
      customer: data['Client Name'],
      email: data['Email'],
      vat: data['VAT Number'],
      street: data['Street'],
      city: data['City'],
      zip: data['ZIP code']
    })},);
    const result = await res.json();
    return result;
  };

  return (
    <form className='flex flex-col justify-around' onSubmit={handleSubmit((data) => createClient(data))}>
      <Input label='VAT Number' register={register} required onBlur={e => {populateVatResult(e.currentTarget.value);}}/>
      <Input label='Client Name' register={register} required value={client} onChange={e => setClient(e.target.value)} />
      <Input label='Email' register={register}/>
      <Input label='Street' register={register} required value={street} onChange={e => setClient(e.target.value)}/>
      <Input label='City' register={register} required value={city} onChange={e => setClient(e.target.value)}/>
      <Input label='ZIP code' register={register} required value={zip} onChange={e => setClient(e.target.value)}/>
      <Button type='submit' />
    </form>
  );
};

export default ClientForm;

What is the best way to close the Modal from within the ClientForm upon successful submission to the database? After saving the data to the database, my aim is to close the Modal and view the Table, with all the saved records, again.

Any suggestions on resolving this issue? Should I have taken a different approach by creating a Modal per type I wish to save, like Clients, Projects, etc., rather than having a general Modal component?

Cheers!

Answer №1

To enable communication between components, consider using the useRef hook as it provides efficient access.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Every time I attempt to initialize a React project using the command "npx create-react-app," I encounter the error message "enoent ENOENT: no such file or directory."

I recently attempted to start a new React project and encountered the following issue: (node:4840) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 close listeners added to [TLSSocket]. Use emitter.setMaxListeners() to increase ...

The issue with the <Button> component not properly linking in next.js

Having trouble with a button wrapped inside a custom Navbar component. The code snippet in question is: <NavBtn> <Link href="/contact" passHref> <Button> Contact Me </Button> </Link> & ...

Vercel deployed Next-App encountering issues: Request for a new refresh token triggers an unexpected 304 Not Modified response

For my latest project, I developed a Next.js frontend app and deployed it on Vercel, along with a Django backend app on Heroku. The authentication mechanism I used involves JWTs and a connection between the Next.js frontend and Django backend through a Nex ...

Facing a multitude of errors while transitioning from Material-ui version 0.10.1 to 0.17

We've encountered quite significant changes between these versions, requiring us to upgrade 40 libraries in order to update React.js. The biggest challenges seem to stem from material-ui. Unfortunately, we can't find any documentation on how to ...

How can I display helperText in a red color using material-ui in reactjs?

My aim is to display the helperText in red color similar to when an error occurs, but I am facing difficulty achieving this. I can't seem to pinpoint where I am making a mistake. Below is the code snippet: class Sample extends React.Component<Prop ...

Create your own unique Semantic UI themes using the Semantic UI theme builder, complete with support for Font Awesome classnames and the ability to preview them with the

My admiration for Semantic UI and Semantic UI React knows no bounds. Not only are they phenomenal libraries, but their documentation is truly a work of art. Yet, crafting and keeping up with themes for these components can be quite the challenge. The task ...

Experiencing difficulties when testing a React Material UI form using React unit tests for beginners

I've encountered an issue with a simple form consisting of a single text field. The form utilizes the React Material UI library and Formik for validations and verification. Unfortunately, I'm facing difficulties in accessing the textfield within ...

"Experience the power of React Swiper 6.8.4 as it unveils its slides only during window resizing or when

I'm a beginner in the world of coding and react, and I've encountered an issue with Swiper 6.8.4 in my React app after implementing a FilterMethod. My goal was to create a Slider containing Projects/Images as Slides, allowing users to filter thes ...

React Webpack - Issue: Module doesn't function as a loader (must have a regular or pitch function)

My webpack.config.js var path = require("path") var webpack = require('webpack') var BundleTracker = require('webpack-bundle-tracker') module.exports = { context: __dirname, entry: [ 'webpack-dev-server/client?ht ...

Harness the power of MDX component props in Codehike Bright for seamless integration with Next.js

Currently, I am utilizing Codehike Bright alongside NextJS 13.2 in my app directory, which involves React Server Components integration. In addition to this setup, I am also incorporating MDX. Within the TSX file named page.tsx, the MDX content is loaded ...

Manipulate Nested Objects using an Array of Keys

Currently, I am developing a recursive form using React and MUI that is based on a nested object. Throughout this process, it is crucial for me to keep track of the previous keys as I traverse through the recursion. As users interact with the form and mak ...

The function you are trying to access does not exist in this.props

Trying to pass this.state.user to props using the isAuthed function is resulting in an error: this.props.isAuthed is not a function . The main objective is to send this.state.user as props to App.js in order to show or hide the Sign out button based on ...

Modify the text field's color when it is in a disabled state

When the text field is disabled, I want to change its color. Below is the code I have written for enabled and disabled states. The style works correctly when the text field is enabled. const StyledTextField = styled(({ dir, ...other }) => <TextFiel ...

Upon installing React using the 'create react app' command and adding additional packages, the package.json file is updated

I am completely new to working with React. I followed the steps to create a React application using the command 'create react app'. After running the command, various files and directories were generated in the root directory, such as package.js ...

Avoid altering the background color when adjusting the scale view on an apex chart due to changes in graph data

I have developed Apexchart components for line charts that come with a date filter picker feature. This chart is interactive and changes dynamically based on the series data provided. function DisplayChart({ series, xaxis }: { series: any; xaxis?: any }) ...

The ideal login page design

I apologize for my lack of knowledge in React, but I am quite new to it and have been struggling with this issue for days. I am having trouble creating a login page in ReactJS. Here is the code in my app.js: import React from 'react'; import {Ha ...

Is there a way to alter the styling of a React element without resorting to querySelector?

Just diving into React and I'm faced with a challenge - how to update the CSS of a class based on a condition. let customizeColumn = document.querySelector(".main-table-body"); !expandFilter ? customizeColumn.setAttribute("style", ...

Sort through an array of objects using the Filter API to find objects with matching

I need assistance in dynamically filtering my array based on a condition where values from one array match another static array. The array nfts is dynamic and changes depending on the user. It contains metadata, images, transaction information, etc. Speci ...

Ways to align elements horizontally while preventing them from shifting positions

I'm faced with a layout challenge where I need to place 2 components side by side, but I want one component to stay on the right without affecting the orientation of the other component. Example: https://i.stack.imgur.com/T5Ram.png Currently, when I ...

Problem encountered when attempting to dynamically add an Option element to a Select element using ReactJS

My project is nearly complete, but I am facing a small bug in my dynamic dropdown box. Whenever a new expense is added to the list, the corresponding year is supposed to be added to the options tag within the select tag in the FilterExpense.jsx file. Howev ...