Struggling with obtaining react-modal in my React Component

Greetings to all React developers out there, especially the newbies like me. I am currently facing an issue with implementing react-modal in my React Component based on this example here. Unfortunately, I have encountered several errors that are proving difficult for me to resolve.

import React, {useState} from 'react';
import {
  Card, Button, CardImg, CardTitle, CardText, CardGroup,
  CardSubtitle, CardBody, CardFooter, CardHeader, CardColumns, CardDeck
} from 'reactstrap';
import Config from 'config';
import parse from 'html-react-parser';
import "./Item.css";
import ReactDOM from 'react-dom';
import Modal from 'react-modal';

const customStyles = {
    content: {
        top: '50%',
        left: '50%',
        right: 'auto',
        bottom: 'auto',
        marginRight: '-50%',
        transform: 'translate(-50%, -50%)',
    },
};

//Modal.setAppElement('FeaturedCards');

class FeaturedItems extends React.Component {
    constructor() {
        super();
        this.state = {
            name: 'React',
            apiData: [],
        };
    }

    async componentDidMount() {
        const tokenString = sessionStorage.getItem("token");
        const token = JSON.parse(tokenString);

        let headers = new Headers({
            "Accept": "application/json",
            "Content-Type": "application/json",
            'Authorization': 'Bearer ' + token.token
        });

        const response = await fetch(Config.apiUrl + `/api/Items/GetFeaturedItems`, {
            method: "GET",
            headers: headers
        });
        const json = await response.json();
        console.log(json);
        this.setState({ itemList: json });
    }

    render() {
        const [modalIsOpen, setIsOpen] = useState(false);
        const items = this.state.itemList;
        let subtitle;

        function handleClick(item) {
            console.log('this is:', item);
            setIsOpen(true);
        }

        function afterOpenModal() {
            // references are now sync'd and can be accessed.
            subtitle.style.color = '#f00';
        }

        function closeModal() {
            setIsOpen(false);
        }

        var formatter = new Intl.NumberFormat('en-US', {
            style: 'currency',
            currency: 'USD'            
        });

        return (
            <div>
                <CardColumns>
                    {items && items.map(item =>
                        <>
                            <Card key={item.itemNumber} tag="a" onClick={() => handleClick(item)} style={{ cursor: "pointer" }}>
                                <CardHeader tag="h3">Featured</CardHeader>
                                <CardImg top className="card-picture" src={"data:image/png;base64," + item.images[0]?.ImageData)} id={item.itemNumber + "Img"} alt={item.itemNumber} />
                                <CardBody className="card-body">
                                    <CardTitle tag="h5">{item.itemNumber}</CardTitle>
                                    <CardSubtitle tag="h6" className="mb-2 text-muted">{item.categoryName}</CardSubtitle>
                                    <CardText className="card-description">{item.itemDescription}</CardText>
                                </CardBody>
                                <CardFooter className="text-muted">{formatter.format(item.price)}</CardFooter>
                            </Card>
                            <Modal
                                isOpen={modalIsOpen}
                                onAfterOpen={afterOpenModal}
                                onRequestClose={closeModal}
                                style={customStyles}
                                contentLabel="Example Modal">
                                    <h2 ref={(_subtitle) => (subtitle = _subtitle)}>Hello</h2>
                                    <button onClick={closeModal}>close</button>
                                    <div>I am a modal</div>
                                    <form>
                                        <input />
                                        <button>tab navigation</button>
                                        <button>stays</button>
                                        <button>inside</button>
                                        <button>the modal</button>
                                    </form>
                            </Modal>
                        </>
                    )}                
                </CardColumns>
            </div>
        );
    }
}
export default FeaturedItems;

I seem to be stuck with a few errors:

  1. Where exactly should
    const [modalIsOpen, setIsOpen] = useState(false)
    be placed to prevent encountering Error: Invalid hook call?
  2. How should I use
    Modal.setAppElement('FeaturedCards')
    , because it does not work with FeaturedCards?

Your assistance on this matter will be greatly appreciated.

Answer №1

Thanks to the valuable feedback from @Nick and @DaveNewton...

...
Modal.setAppElement('#root');
...

class FeaturedCards extends React.Component {
    constructor() {
        super();
        this.state = {
            name: 'React',
            apiData: [],
            isOpen: false            
        };
        
    }

    ...    

    render() {
        const items = this.state.itemList;
        let subtitle;
        
        // Binding for proper function execution  
        handleClick = handleClick.bind(this);
        closeModal = closeModal.bind(this);

        function handleClick() {
            this.setState({ isOpen: true });
        }

        function closeModal() {
            console.log('Clicked close button')
            this.setState({ isOpen: false });
        }

        function afterOpenModal() {
            // Update style once modal is opened
            subtitle.style.color = '#f00';
        }

        return (
            <div>
                <CardColumns>
                    {items && items.map(item =>
                        <>
                            <Card key={item.itemNumber} tag="a" onClick={() => handleClick()} style={{ cursor: "pointer" }}>
                                <CardHeader tag="h3">Featured</CardHeader>
                                <CardImg top className="card-picture" src={"data:image/png;base64," + item.images[0]?.ImageData} id={item.itemNumber + "Img"} alt={item.itemNumber} />
                                <CardBody className="card-body">
                                    <CardTitle tag="h5">{item.itemNumber}</CardTitle>
                                    <CardSubtitle tag="h6" className="mb-2 text-muted">{item.categoryName}</CardSubtitle>
                                    <CardText className="card-description">{item.itemDescription}</CardText>
                                </CardBody>
                                <CardFooter className="text-muted">{formatter.format(item.price)}</CardFooter>
                            </Card>
                            <Modal
                                isOpen={this.state.isOpen}
                                onAfterOpen={afterOpenModal}
                                onRequestClose={() => closeModal()}
                                style={customStyles}
                                contentLabel="Example Modal">
                                    <h2 ref={(_subtitle) => (subtitle = _subtitle)}>Hello</h2>
                                <button onClick={() => closeModal()}>close</button>
                                    <div>I am a modal</div>
                                    <form>
                                        <input />
                                        <button>tab navigation</button>
                                        <button>stays</button>
                                        <button>inside</button>
                                        <button>the modal</button>
                                    </form>
                            </Modal>
                        </>
                    )}                
                </CardColumns>
            </div>
        );
    }
}
export default FeaturedCards;

... With the advice from @Nick and @DaveNewton, I successfully managed to implement both opening and closing functionalities for the modal.

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

Could you please direct me to the section in the ECMAScript documentation that specifies the behavior of a resolved promise with its [[Promise

My objective is to compare the behavior of a promise's resolve function with the corresponding process outlined in the ECMAScript specification. Specifically, I am interested in understanding how the resolve function behaves when called with an object ...

Is there a way to use HTML and JS to draw custom lines connecting elements?

Sorry if this question has been asked before. Is there a way to create straight lines connecting HTML elements with just HTML and JavaScript, without relying on SVG or Canvas? If so, what would be the most effective approach? ...

What is the best way to receive a user's input date in Dynamics 365 using HTML/JavaScript?

My HTML webform is set up to capture user input like address, card number, city, and state in text format. However, within Microsoft Dynamics 365, I have a custom entity with fields for this information. When a user completes the webform and submits it, a ...

Synchronized loops in jQuery using the .each method

I'm having trouble getting the ajaxStop function in jquery to work. Any suggestions on how to make it fire? My goal is to iterate through each anchor tag and update some content within it. After that, I want to use the ajaxstop event to trigger a scr ...

Filling out a form within a webpage fetched through a DOMParser

Creating automation software in JavaScript using TamperMonkey. The script performs several AJAX requests that retrieve HTML to be parsed with a DOMParser. Is there a way to submit these forms without opening the newly retrieved HTML on the main page? ...

When using Browserify, the function require() on a concatenated string will not include the module in the output script

When using require() to create a combined string path, the path of the module will not be included in the output script. Examples of this include: require("./"+"b" ); //or var path="./"; require(path+"b"); Let's say we have a.js module.exports="a"; ...

A guide on integrating array map with a v-for loop in Vue

Struggling to understand how to implement a loop within another loop in Vue? This task might seem simple with React, but Vue presents its own challenges when it comes to using loops with arrays in templates/JSX. The input data follows a specific format fr ...

JavaScript library jQuery is unable to locate the element tagged as "<."

I've encountered an issue with setting the value of dropdown options in a web page using strings that contain < and >. Here is an example code snippet: <select id="m" name="m" > <option value="" selected="selected" >All</option& ...

Should one prioritize learning TypeScript over diving into Angular2?

Should I prioritize learning TypeScript before diving into AngularJS 2? ...

Is it possible to encase <v-img> within an anchor element?

I am currently using Vuetify 1.5 and have included a couple of <v-avatars></v-avatars> elements in which there is a nested <v-img></v-img>. I attempted to enclose the img tags within an a tag but encountered an issue wherein the ima ...

Is it possible to initiate a series of node tasks in a predetermined sequence?

I have developed a framework that currently requires 4 user inputs to install, which is quite cumbersome. I am looking for a way to streamline the process to just one input. Essentially, I am seeking a solution to execute those 4 commands with only one in ...

Step-by-step guide to implementing onClick functionality within a component

Currently, I am utilizing https://github.com/winhtaikaung/react-tiny-link to showcase posts from various blogs. While I am able to successfully retrieve the previews, I am facing an issue with capturing views count using onClick(). Unfortunately, it appear ...

The jQuery ajax function functions flawlessly on a local environment, but encounters issues when used on a

After spending the entire day researching this issue, it appears to be a common problem without a solution in sight. The challenge I am facing involves using jquery's $.ajax() function to update database values through a service call. While it works ...

How to apply CSS styling to a specific element using jQuery

When using $(".className"), all elements with the class .className are returned. How can I target a specific element by its index number to apply styling only to that element? <html> <head> <script src="https://ajax.googleapis.com/ajax ...

Using Javascript to trigger a setTimeout function after the user's mouse leaves

There is a div that pops up when the user's mouse exits the webpage, containing a survey pertaining to my website. I want to avoid prompting users to take the survey if they move their cursor out of the page within the first few minutes of browsing. ...

Iterating over a range of values with _.each()

Can someone help me figure out why my syntax is incorrect for applying two values from different iteratees (day.classes and event.part) on line 5? <div class="days"> <div class="headers"> <% _.each(daysOfTheWeek, function(day) { %&g ...

JavaScript-powered dynamic dropdown form

I need help creating a dynamic drop-down form using JavaScript. The idea is to allow users to select the type of question they want to ask and then provide the necessary information based on their selection. For example, if they choose "Multiple Choice", t ...

Removing a specific item from an array

state = { filters: ['all'] } this.state.filters.includes('humans') ? this.state.filters.filter(val => val !== 'humans') : this.state.filters.push(dropdown) I have a condition set up so that when I click on a button, ...

What is the process for obtaining authorization to access user information?

I am facing a perplexing issue with my app settings. Despite setting everything up correctly, I am unable to authenticate my account on my website using the Javascript SDK. Whenever I try to console.log(me), I only receive public information. Upon furthe ...

Enhance your websites' search functionality with jQuery autocomplete using AJAX

I am attempting to implement dynamic autocomplete values for a text box. Here is my solution: echo json_encode($res) 0: {type_name: "name1"} 1: {type_name: "name2"} 2: {type_name: "name3"} 3: {type_name: "name4"} 4: {type_name: "name5"} Below is the co ...