Code Playground.

How to Render a React Component Inside a Bootstrap Popover

CFG

How to Render a React Component Inside a Bootstrap Popover

Introduction 

Now and then you end up needing more than the libraries you are utilizing bring to the table. For instance, suppose you need to render a React part inside a bootstrap popover. Sounds simple, isn't that so? All things considered, it turns out not to be that basic. This guide will additionally investigate this situation and offer two methodologies for rendering a part inside a bootstrap popover. 

Customary Static Projects 

Accept you have a standard static venture with no moduler or transpiler, simply exceptionally essential HTML documents that are bootstrap connected over various pages. 

You'll have the Bootstrap CSS interface in the head, and the jQuery, Popper.js and Bootstrap content not long before the body closes. The fundamental HTML layout would look as follows.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Static Template Demo CrowdforGeeks</title>
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
      integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
      crossorigin="anonymous"
    />
  </head>
  <body>
    <!-- -->

    <script
      src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
      integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"
      integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
      integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
      crossorigin="anonymous"
    ></script>
  </body>
</html>

Add the Popover Button

Create a button that will trigger the popover. Give it an id of value popover.

<button type="button" class="btn btn-lg btn-primary" id="popover">
  Click to toggle popover
</button>

Before the body ends, write a <script> block and initialize the popover by selecting the id of the button.

<script>
  $(document).ready(function() {
    $("button#popover").popover();
  });
</script>

As desired, pass a few options into the popover() to display HTML content in it.

$("button#popover").popover({
  html: true,
  content: `<div>Hello</div>`
});

You can see the popover in action when you click on the button.

Now, instead of directly putting in the content, you will add a React component.

Insert React Component

First, add the React CDN links to the HTML file.

<script
  crossorigin
  src="https://unpkg.com/react@16/umd/react.development.js"
></script>
<script
  crossorigin
  src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"
></script>

Since there are no modulers or transpilers, you will have to use the React.createElement() function to create a component instead of writing JSX.

const Hello = props => React.createElement("div", null, `Hello ${props.to}!`);

Now, where do you render this component? Oh, that's simple you can do the following, right?

$(document).ready(function() {
  $("button#popover").popover({
    html: true,
    content: `<div id='app'></div>`
  });
  const Hello = props => React.createElement("div", null, `Hello ${props.to}!`);

  ReactDOM.render(
    React.createElement(Hello, { to: "World" }, null),
    document.getElementById("app")
  );
});

Unfortunately, this won't work because the popover is initialized and the HTML content inside the popover is added by jQuery. Hence, ReactDOM.render() method will not be able to find the DOM node.

Also Read:-How to Get JSON Data from PHP Script using jQuery Ajax

To get around this problem, create a DOM element and then access its innerHTML property inside the popover content.

$(document).ready(function() {
  const a = document.createElement("div");

  const Hello = props => React.createElement("div", null, `Hello ${props.to}!`);

  ReactDOM.render(React.createElement(Hello, { to: "World" }, null), a);

  $("button#popover").popover({
    html: true,
    content: a.innerHTML
  });
});

If you want to display a static component, then this will work for you. But if you need interactivity inside the popover, that's something not possible with Bootstrap currently. Bootstrap does not have proper hooks to facilitate interactive behavior.

But if this was a bundled project with a transpiler, we could use the reactstrap library to add interactivity inside the popover component.

Projects with Reactstrap Library

Add reactstrapbootstrap, and jquery in your dependencies.

npm i reactstrap bootstrap jquery

In the main file, create a basic popover .

import "bootstrap/dist/css/bootstrap.min.css";
import { Button, Popover, PopoverHeader, PopoverBody } from "reactstrap";

const App = props => {
  const [popoverOpen, setPopoverOpen] = useState(false);

  const toggle = () => setPopoverOpen(!popoverOpen);

  return (
    <div
      className="d-flex align-items-center justify-content-center"
      style={{ height: "100vh" }}
    >
      <Button id="Popover1" type="button" color="primary">
        Launch Popover
      </Button>
      <Popover
        placement="bottom"
        isOpen={popoverOpen}
        target="Popover1"
        toggle={toggle}
      >
        <PopoverHeader>Popover Title</PopoverHeader>
        <PopoverBody>This the Popover body</PopoverBody>
      </Popover>
    </div>
  );
};

Reactstrap's <Popover /> component allows you to have React components as the children. This means that the children can have state of their own and can provide interactive behavior.

Let's add a <Counter /> component, inside which there will be a <Button /> component that will increment the counter.

const Counter = () => {
  const [counter, setCounter] = useState(0);

  return (
    <div>
      <Button onClick={() => setCounter(counter + 1)}>Click</Button>

      <span className="ml-3">{counter}</span>
    </div>
  );
};

Inside the <PopoverBody /> component, call the counter.

<PopoverBody>This the Popover body</PopoverBody>

Now, when you click on the popover button, it displays the Popover component with a counter embedded inside of it .

Also Read:-How to Create a React Application and Deploy It on GitHub Pages

Putting it all together, you'll have the components as follows.

import React, { useState } from "react";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
import { Button, Popover, PopoverHeader, PopoverBody } from "reactstrap";

const Counter = () => {
  const [counter, setCounter] = useState(0);

  return (
    <div>
      <Button onClick={() => setCounter(counter + 1)}>Click</Button>

      <span className="ml-3">{counter}</span>
    </div>
  );
};

const App = props => {
  const [popoverOpen, setPopoverOpen] = useState(false);

  const toggle = () => setPopoverOpen(!popoverOpen);

  return (
    <div
      className="d-flex align-items-center justify-content-center"
      style={{ height: "100vh" }}
    >
      <Button id="Popover1" type="button" color="primary">
        Launch Popover
      </Button>
      <Popover
        placement="bottom"
        isOpen={popoverOpen}
        target="Popover1"
        toggle={toggle}
      >
        <PopoverHeader>Popover Title</PopoverHeader>
        <PopoverBody>
          <Counter />
        </PopoverBody>
      </Popover>
    </div>
  );
};

export default App;

Conclusion

This guide told you the best way to include a static React segment inside a bootstrap popover and how to add intelligence to the popover utilizing an increasingly refined library like reactstrap. These strategies will come convenient when you are constrained by the libraries utilized in your undertaking. By the by, guarantee that you generally make a packaged undertaking utilizing formats like make respond application to stay away from fluffy hacks at last.

Also Read:-How to Connect a MySQL Database in NodeJS




CFG