geudrik
geudrik

Reputation: 672

Modal Component - How to include and open/close from another component

I'm just starting to learn React. I've got a modal component (that's basically a wrapper for react-bootstrap's Modal component). The idea is to have a "Feedback" modal that I can include in various places. This approach isn't working, and I don't know what I don't know :/

Below is a quick example of what I mean / how I'm trying to display my modal component

import React, { Component } from 'react'
import Modal from 'react-bootstrap/Modal'
import Button from "components/button/button"

export class BaseModal extends Component {

    constructor(props) {
        super(props);
        this.state = { show: false };
    }

    toggleModal() {
        this.setState({ show: !this.state.show })
    }

    render() {
        if (!this.props.show) {
            return null;
        };
        return (
            <>
                <Modal show={this.state.show}>
                    <Modal.Header closeButton>
                        <Modal.Title>Modal heading</Modal.Title>
                    </Modal.Header>
                    <Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
                    <Modal.Footer>
                        <Button variant="secondary" onClick={this.toggleModal}>
                            Close
                        </Button>
                        <Button variant="primary" onClick={this.toggleModal}>
                            Save Changes
                        </Button>
                    </Modal.Footer>
                </Modal>
            </>
        )
    }
}

A simple page like this - clicking this button doesn't do anything (React dev tools show no BaseModal node in the vdom)

import React, { Component } from 'react'
import Button from "components/button/button"
import BaseModal from "components/modals/baseModal"

export class ButtonDocs extends Component {
    render() {
        <Button value="Open Modal" onClick={BaseModal.toggleModal} />
    }
}

Upvotes: 1

Views: 4435

Answers (1)

Travis James
Travis James

Reputation: 1939

You can't just import a Component and then call a method on it, because you aren't actually rendering it anywhere.

What you need to do is render the Component, and then if you want to control the state of one component from another you need to "lift state up" and pass the state and any methods needed to the modal component as props. Something like this:

Modal Component

import React, { Component } from 'react'
import Modal from 'react-bootstrap/Modal'
import Button from "components/button/button"

export class BaseModal extends Component {

    render() {
        if (!this.props.show) {
            return null;
        };
        return (
            <>
                <Modal show={this.state.show}>
                    <Modal.Header closeButton>
                        <Modal.Title>Modal heading</Modal.Title>
                    </Modal.Header>
                    <Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
                    <Modal.Footer>
                        <Button variant="secondary" onClick={this.props.toggleModal}>
                            Close
                        </Button>
                        <Button variant="primary" onClick={this.props.toggleModal}>
                            Save Changes
                        </Button>
                    </Modal.Footer>
                </Modal>
            </>
        )
    }
}

Button Docs

import React, { Component } from 'react'
import Button from "components/button/button"
import BaseModal from "components/modals/baseModal"

export class ButtonDocs extends Component {

constructor(props) {
        super(props);
        this.state = { show: false };
    }

    toggleModal() {
        this.setState({ show: !this.state.show })
    }

    render() {
        <Button value="Open Modal" onClick={this.toggleModal} />
        <BaseModal show={this.state.show} toggleModal={this.toggleModal} />
    }
}

Upvotes: 2

Related Questions