Create dynamic modals in ReactJS that appear when a row is clicked

Engaged in a project for an undisclosed entity where patient data is retrieved from their API and displayed as modal on the page. Clicking on a modal reveals more threat information in another modal. The objective is for these modals to render based on a click within a specific div.

How can I effectively transfer the data from the API to the modal component with each click?

Div table-like behavior on click

import React, {useState, useEffect} from 'react';

const keys = Object.keys(arr[0]);

// const handleOnClick = param => {
//   console.log('do something: ', param);
// }

export default function Demo() {
  const [isModalOpen, setModalIsOpen] = useState(false);
  const [users, setUsers] = useState([]);

    const toggleModal = () => {
        setModalIsOpen(!isModalOpen);
  };
  
  const handleOnClick = () => {
    toggleModal()
  };

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const { data } = await axios.get('https://gist.githubusercontent.com/SkyBulk/a75a32254d58aea2cf27cbb43117a2f4/raw/eb5f85560c0dfd74a4aab9db755ac5a06f0627c2/api.json').results;
        setUsers(data);
      } catch (err) {
        console.error("failed", err);
      }

      setModalIsOpen(false);
    };

    fetchUsers();
  }, []);

  return (
    <div className="container">
        <>
          {keys.map((key) => (
            <div className="col" key={key}>
              <div className="row">{key}</div>
                {arr[0][key].map((item) => (
                  <div className="row" key={item.technique_id} onClick={() => handleOnClick(item)}>{item.technique}</div>
                ))}
            </div>
          ))}
        </>
        {isModalOpen && <Modal onRequestClose={handleOnClick} data={users}/>}
      </div>
  );
}

modal

import React, { useEffect } from "react";

const Modal = ({ onRequestClose, data }) => {
    // Use useEffect to add an event listener to the document
    useEffect(() => {
        function onKeyDown(event) {
            if (event.keyCode === 27) {
                // Close the modal when the Escape key is pressed
                onRequestClose();
            }
        }

        // Prevent scrolling
        document.body.style.overflow = "hidden";
        document.addEventListener("keydown", onKeyDown);

        // Clear things up when unmounting this component
        return () => {
            document.body.style.overflow = "visible";
            document.removeEventListener("keydown", onKeyDown);
        };
    });

    return (
        <div className="modal__backdrop">
            <div className="modal__container">
                <div className="modal-header">
                    <div className="modal-close" onClick={onRequestClose}>
                        <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
                        </svg>
                    </div>
                </div>
                <div className="job-title-wrapper">
                    <div className="job-card-title">{data}</div>
                </div>
            </div>
        </div>
    );
};

export default Modal;

Answer №1

If my understanding is correct, you are looking to trigger a specific API call and populate the modal with its data upon clicking on a row, right?

Your current implementation using useEffect seems to be fetching user data whenever there is an update in your component, which may not align with your requirements. It would be advisable to remove that block entirely.

Instead, the API call should ideally be made when a row is clicked, so it appears more suitable to handle this in your handleOnClick function. Here's how you can modify it:

const handleOnClick = async () => {
 try {
    const { data } = await axios.get('https://api.example.com/users').results;

    setUsers(data);

    // Once the data is fetched, open the modal
    setModalIsOpen(true);
  } catch (err) {
    console.error("Error occurred", err);
  }
};

With these adjustments, the user data should be stored in your user state before opening the modal. After making these changes, your Demo component should resemble the following:

export default function Demo () {
 const [isModalOpen, setModalIsOpen] = useState(false);
  const [users, setUsers] = useState([]);
 
  const handleOnClick = async () => {
     try {
        const { data } = await axios.get('https://api.example.com/users').results;

        setUsers(data);

        // Once the data is fetched, open the modal
        setModalIsOpen(true);
      } catch (err) {
        console.error("Error occurred", err);
      }
  };


  return (
    <div className="container">
        <>
          {keys.map((key) => (
            <div className="col" key={key}>
              <div className="row">{key}</div>
                {arr[0][key].map((item) => (
                  <div className="row" key={item.technique_id} onClick={() => handleOnClick(item)}>{item.technique}</div>
                ))}
            </div>
          ))}
        </>
        {isModalOpen && <Modal onRequestClose={() => setModalIsOpen(false)} data={users}/>}
      </div>
  );
}

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

Obtain the root URL path for React application

I am currently working on a react app using create-react-app and react-router. I am trying to determine the root URL path of my react app, especially since it may be served in different locations: For production: example.com/interface/ For local developm ...

One approach to enhance a function in Typescript involves encapsulating it within another function, while preserving

What I Desire? I aim to create a function called wrap() that will have the following functionality: const func = (x: string) => 'some string'; interface CustomObject { id: number; title: string; } const wrapped = wrap<CustomObject> ...

Efficient ways to clear all input fields within a React div component

import "./App.css"; import { useState } from "react"; import { useSelector, useDispatch } from "react-redux"; import { addUser} from "./features/Users"; function App() { const dispatch = useDispatch(); const use ...

Issues with playing videos on mobile devices using the React Player in the viewport

A custom-built player component was created to play videos while the user is on the viewport and pause when they leave it. The functionality works perfectly fine on browsers, but on mobile devices, the video does not start playing automatically until manua ...

What is the precise description of the CSS property font-size when measured in pixels?

When defining the CSS property font-size, it can be set to a specified length in pixels. What exactly does this measurement describe? Is it the width or height of a particular character (such as 'm'), is it an attribute within the font file desc ...

Sending data from view to controller in Angular using TypeScript

I am currently working with AngularJS and TypeScript, and I have encountered an issue with passing a parameter from the view to the controller. In my attempts to solve this problem, I have utilized ng-init as follows: <div class="col-md-9" ng-controlle ...

Is there a way for me to define the type of a prop based on the type of another prop?

I'm not entirely certain how to phrase this inquiry, or which terminology to employ, so I'll do my best in presenting it. My intention is to develop a component that functions on an array of elements and triggers a render function for each eleme ...

"Looking to swap out the Angular theme's CSS stylesheet for your entire application? Here's

I was initially facing an issue while trying to import CSS through index.html as I kept getting a MIME type error: enter image description here The browser refused to apply the stylesheet from 'http://localhost:4200/css/pink-bluegrey.css' because ...

What is the proper way to handle postMessage events from a Streamlit iframe within a Next.js app?

I'm currently in the process of integrating a Streamlit app into a Next.js application by embedding the Streamlit within an iframe. My main goal is to send data from the Streamlit app to the Next.js parent using window.postMessage, specifically focusi ...

Elements recognized worldwide, Typescript, and a glitch specific to Safari?

Consider a scenario where you have a select element structured like this: <select id="Stooge" name="Stooge"> <option value="0">Moe</option> <option value="1">Larry</option> <option value="2">Curly</option ...

HTML / CSS / JavaScript Integrated Development Environment with Real-time Preview Window

As I've been exploring different options, I've noticed a small but impactful nuance. When working with jQuery or other UI tools, I really enjoy being able to see my changes instantly. While Adobe Dreamweaver's live view port offers this func ...

Enable the automatic hiding of the filter menu in MUI DataGrid when the enter key is

Is there a method to automatically close the filtering menu in MUI DataGrid when pressing the enter key? Currently, we have to click elsewhere to hide it. This issue pertains to: ...

When does server-side rendering become a poor choice?

One of the major benefits of using Nextjs with React is the ease of implementing server-side rendering (SSR). Not only does SSR provide advantages such as improved performance and SEO, but it also raises the question: With these benefits in mind, should ...

The alignment for Bootstrap's NAV element within a display:table-cell element seems to be off when viewed on Firefox浪

Here is an example of HTML markup with Bootstrap library included: <div class="container"> <div class="card"> <ul class="nav list"> <li class="element"> <a href="#">Element</a> </li> ...

Retrieving data from getServerSideProps and utilizing it inside Layout component in Next.js

Currently, I am in the process of developing a web application with Next.js. This project involves creating an admin dashboard that will be utilized to manage various tasks, each with its own SSR page. DashboardLayout : export const DashboardLayout = ({ch ...

After deploying my project with Netlify, I encountered an unexpected problem where the Stripe checkout is redirecting to the Stripe payment page

Hey there, I'm currently working on integrating stripe checkout into my webapp. Whenever I click on the "purchase button" to redirect to the stripe checkout page, I encounter an error message: VM97:1 Uncaught (in promise) SyntaxError: Unexpected token ...

Ways to bypass browser pop-up blockers when using the window.open function

I am displaying an HTML retrieved from the backend. printHtml(htmlContent) { var windowToPrint = window.open('', '_blank'); windowToPrint.document.write(htmlContent); setTimeout(function () { windowToPrint.document ...

Personalized CSS styling for Jquery Mobile version 1.3

Having trouble with styling a page in jquery using CSS, specifically aligning #navgroup to the center of the footer and removing an additional white counter from the slider. Here is my code: <!doctype html> <html lang="en> <head> < ...

Error message: Unable to access property 'string' as it is undefined | React.PropTypes | LayoutPropTypes.js

Recently, I deleted and reinstalled my node_modules folder, and now I'm encountering a perplexing issue in the LayoutPropTypes.js file. Within node_modules/react-native/Libraries/StyleSheet/LayoutPropTypes.js, I'm noticing that the variable var ...

Avoiding memory leaks in Reactjs when canceling a subscription in an async promise

My React component features an async request that dispatches an action to the Redux store from within the useEffect hook: const fetchData = async () => { setIsLoading(true); try { await dispatch(dataActions.fetchData(use ...