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

The combination of sass-loader and Webpack fails to produce CSS output

Need help with setting up sass-loader to compile SCSS into CSS and include it in an HTML file using express.js, alongside react-hot-loader. Check out my configuration file below: var webpack = require('webpack'); var ExtractTextPlugin = require ...

Positioning the jQuery mobile navBar to be fixed on iOS 4 devices

Currently working on a mobile app with jquery using iOS4 and iOS5 compatibility as the final hurdle. While fixing the navigation bar is simple on iOS5 with position:fixed, it's not as straightforward on iOS4! I've experimented with various soluti ...

The Cordova minification tool fails to compress files within the browser platform

I recently installed the cordova-minify plugin to compress the javascript code in my Cordova app. When I tried running the command: cordova build browser An output message appears: cordova-minify STARTING - minifying your js, css, html, and images. ...

Unusual gaps of white space appearing between React components

Currently developing a small web application with multiple components. The backend functionality is all set, but encountering an unusual styling issue. Specifically, noticing a white space appearing between each component without any clear reason. This ga ...

Tips for avoiding anchor tag text from being split across two lines when resizing

One issue I am facing is with an anchor tag that displays the name of the logged-in person. The problem arises when resizing the browser window, causing the name to split across two lines. Is there a way to prevent this from happening? ...

Alter the navigation but keep the URL intact without modifying the view

I have an Angular project that includes a login component. The login component is located in the directory app/main/login. I am trying to navigate to the login component from app.component.html using a button. Below is the code snippet from my app-routi ...

Integrate Angular 2 components into WebStorm

I am currently working on a project using Angular 2 (rc5) and TypeScript (1.8.10). Angular 2 is built with TypeScript, but in the node_modules directory, I notice that there are JavaScript files (*.js) along with declaration files (*.d.ts). It makes it di ...

Chrome Bug with Fixed Position Background

Just finished creating a website that features fixed images as backgrounds with text scrolling on top of them. I've noticed an issue when using Chrome - the scrolling stops briefly between backgrounds, pauses for about a second, and then resumes. I&ap ...

Exploring Grails Assets, Redirections, Secure Sockets Layer, and Chrome

Using Grails 2.1.1 with the resources plugin, I have encountered an issue when incorporating the jstree library which comes with themes configuration: "themes":{ "theme":"default", "dots":false, "icons":true } The JavaScript in the library locat ...

What are some effective ways to integrate the WordPress API with ReactJS?

Wordpress recently introduced an API that allows you to make HTTP requests without worrying about routes, as the backend is handled for you. I'm curious, how can I integrate ReactJs with Wordpress API? This has been a frustrating challenge for me be ...

The Angular tag <mat-expansion-panel-header> fails to load

Every time I incorporate the mat-expansion-panel-header tag in my HTML, an error pops up in the console. Referencing the basic expansion panel example from here. ERROR TypeError: Cannot read property 'pipe' of undefined at new MatExpansionPanel ...

When the typeof x is determined to be "string", it does not result in narrowing down to just a string, but rather to T & string

Could someone help me understand why type narrowing does not occur in this specific case, and return typing does not work without using: as NameOrId<T>; Is there a more efficient way to rewrite the given example? Here is the example for reference: ...

Show the user's chosen name in place of their actual identity during a chat

I'm facing an issue where I want to show the user's friendly name in a conversation, but it looks like the Message resource only returns the identity string as the message author. I attempted to retrieve the conversation participants, generate a ...

Unexpected issue with React onClick function in production environment

With my expertise, I crafted a function that alters the class of a div tag upon clicking an image. At first glance, it simply reveals a dropdown menu when the hamburger icon is clicked. While this functionality performs seamlessly in development mode, it e ...

Changing the color of a Highcharts series bar according to its value

Playing around with Highcharts in this plunker has led me to wonder if it's possible to dynamically set the color of a bar based on its value. In my current setup, I have 5 bars that change values between 0 and 100 at intervals. I'd like the colo ...

Ways to compel divs underneath aligned divs

There are six divs numbered 1 to 6. I want divs 2, 4, and 6 to be positioned below divs 1, 3, and 5 respectively. Is it possible to achieve this layout? Sorry if my explanation is not very clear. Thank you. http://jsfiddle.net/LkGV8/ <body> <d ...

Ways to center items in a row-oriented collection

When dealing with a horizontal list, the issue arises when the first element is larger than the others. This can lead to a layout that looks like this. Is there a way to vertically align the other elements without changing their size? I am aware of manual ...

Utilizing React Google Maps and React Places Auto Complete: It appears that the Google Maps JavaScript API has been integrated multiple times within this page

For my 2 components, I find myself needing to incorporate the Google Maps API twice. This has led to an error message stating that the Google Maps JavaScript API has been included multiple times on the page. Removing the initial Google Map API link in inde ...

Encountered an issue while attempting to authenticate CMS signature using pkijs

I am attempting to validate a CMS signature generated with open ssl using the following command: $ openssl cms -sign -signer domain.pem -inkey domain.key -binary -in README.md -outform der -out signature Below is my code utilizing pkijs: import * as pkij ...

The Battle of Identifiers: Named Functions against Anonymous Functions in TypeScript

When it comes to performance and performance alone, which option is superior? 1) function GameLoop() { // Performing complex calculations requestAnimationFrame(GameLoop); } requestAnimationFrame(GameLoop); 2) function GameLoop() { // ...