{"componentChunkName":"component---gatsby-theme-teklog-src-templates-post-tsx","path":"/how-to-create-single-modal-in-gatsby-using-reactstrap-react-portals-react-context-and-react-custom-hooks","result":{"data":{"site":{"siteMetadata":{"siteUrl":"https://blog.tekmi.nl","author":{"name":"Teklog","avatar":"/img/tekmi-icon.svg"}}},"blogPost":{"frontmatter":{"title":"How to create Single Modal in Gatsby using Reactstrap, React Portals, React Context and React Custom Hooks","slug":"how-to-create-single-modal-in-gatsby-using-reactstrap-react-portals-react-context-and-react-custom-hooks","series":null,"date":"2019-08-03","datePretty":"03 August, 2019","coverImage":{"childImageSharp":{"fixed":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAUCAwQG/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/9oADAMBAAIQAxAAAAGe7n7crwRBf//EABoQAAIDAQEAAAAAAAAAAAAAAAABAgMhEiL/2gAIAQEAAQUConFryKyuJiFp0f/EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/AYf/xAAWEQADAAAAAAAAAAAAAAAAAAABEBL/2gAIAQIBAT8Bor//xAAbEAACAQUAAAAAAAAAAAAAAAAAATEQESGRwf/aAAgBAQAGPwLLJLcrD2f/xAAcEAEAAgEFAAAAAAAAAAAAAAABABEhQXGBobH/2gAIAQEAAT8hoVT7Bkbl2hlpV2jpekQOeKf/2gAMAwEAAgADAAAAEKvv/8QAFxEBAAMAAAAAAAAAAAAAAAAAAAERYf/aAAgBAwEBPxDKpf/EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxCjX//EABsQAQEBAAIDAAAAAAAAAAAAAAERADFRYXHB/9oACAEBAAE/EIeD3xkMAngXLmxGot8ygOkCJpzISPdy4V7Q3//Z","width":1000,"height":750,"src":"/static/a749dcb5ee570896858cbe828a2cec3f/a7715/bankViewLake.jpg","srcSet":"/static/a749dcb5ee570896858cbe828a2cec3f/a7715/bankViewLake.jpg 1x"}}},"author":null,"authorAvatar":null},"timeToRead":11,"excerpt":"Introduction Gatsby is a free and open-source static site generator based on React. In this tutorial, we will use the default starter kit with…","html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p><a href=\"https://www.gatsbyjs.org/\">Gatsby</a> is a free and open-source static site generator based on React. In this tutorial, we will use the default starter kit with cosmetic modifications.</p>\n<p><a href=\"https://reactstrap.github.io/\">Reactstrap</a> provides React components based on Bootstrap 4 library. It comes with a powerful <a href=\"https://github.com/reactstrap/reactstrap/blob/master/src/Modal.js\">Modal</a> component and his three supporting sub-components:</p>\n<ul>\n<li><a href=\"https://github.com/reactstrap/reactstrap/blob/master/src/ModalHeader.js\">ModalHeader</a></li>\n<li><a href=\"https://github.com/reactstrap/reactstrap/blob/master/src/ModalBody.js\">ModalBody</a></li>\n<li><a href=\"https://github.com/reactstrap/reactstrap/blob/master/src/ModalFooter.js\">ModalFooter</a></li>\n</ul>\n<p>Armed with those, you can get a working Model almost in no time. Reactstrap documentation is full of examples, so feel free to explore its <a href=\"https://reactstrap.github.io/components/modals/\">Modals</a> part on your own.</p>\n<p>Out of the box solution is pretty comprehensive, but it forces you to create many Modals. You must control them at least with one show/hide variable and with one toggle function. They are following drawbacks with this approach:</p>\n<ul>\n<li>The more Modals you have, the more variables and toggle functions you need to take care of. You could do it via Higher Order Component, React Context or even via Redux, but it may become troublesome.</li>\n<li>If you wanted to reuse the same Modal between sibling components, you may end up replicating way too much of your JSX code. Also, you would need to introduce some local state in your stateless component.</li>\n</ul>\n<p>The good thing about Reactstrap Modal is that it uses <a href=\"https://reactjs.org/docs/portals.html\">React Portals</a> to render his content into a separate DOM node. So, even if you have dozens of Modals in your JSX tree, only one will be actually rendered. And gladly, it will also sit outside your main DOM tree, where usually your React/Gatsby application is mounted into.</p>\n<p>The less neat part is that this Modal gets added and removed from DOM every time you open or close it. And you cannot even control where it renders into...</p>\n<p>Wouldn't it be ideal if you could pre-render the Modal at the bottom of our HTML, only swapping his content? It is possible, but requires a bit of hack here and there.</p>\n<h2 id=\"tldr\" style=\"position:relative;\"><a href=\"#tldr\" aria-label=\"tldr permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>TL;DR</h2>\n<p>If you can't wait to see the code, I've created a <a href=\"https://github.com/tekmi/blogging-gatsby-modals\">Github repository</a> for you. Otherwise, let's start off our tutorial.</p>\n<h2 id=\"proposal--plan\" style=\"position:relative;\"><a href=\"#proposal--plan\" aria-label=\"proposal  plan permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Proposal / Plan</h2>\n<p>So to get this Single Modal working, we must follow a 7-step plan:</p>\n<ol>\n<li><a href=\"#instruct-gatsby-to-create-a-separate-div-with-id-single-modal\">Instruct Gatsby to create a separate div with id \"single-modal\"</a></li>\n<li><a href=\"#extend-reactstrap-modal-to-render-his-content-inside-this-single-modal-element\">Extend Reactstrap Modal to render his content inside this \"single-modal\" element</a></li>\n<li><a href=\"#wrap-every-gatsby-page-inside-layout-component\">Wrap every Gatsby page inside Layout component</a></li>\n<li><a href=\"#use-react-context-to-create-singlemodalprovider-and-usesinglemodal-custom-hook\">Use React Context to create SingleModalProvider and useSingleModal custom hook</a></li>\n<li><a href=\"#wrap-your-application-within-singlemodalprovider\">Wrap your application within SingleModalProvider</a></li>\n<li><a href=\"#render-extended-modal-at-the-bottom-of-the-layout-with-sane-defaults\">Render Extended Modal at the bottom of the Layout with sane defaults</a></li>\n<li><a href=\"#call-the-modal-from-within-the-gatsby-page\">Call the Modal from within the Gatsby page</a></li>\n</ol>\n<h3 id=\"assumptions\" style=\"position:relative;\"><a href=\"#assumptions\" aria-label=\"assumptions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Assumptions</h3>\n<p>I assume you are comfortable with Gatsby. I also assume you tinkered around with React Context and React Hooks before.</p>\n<p>If not, there are some recommended materials to read, before you proceed.</p>\n<ul>\n<li><a href=\"https://www.gatsbyjs.org/docs/quick-start\">https://www.gatsbyjs.org/docs/quick-start</a></li>\n<li><a href=\"https://reactjs.org/docs/hooks-intro.html\">https://reactjs.org/docs/hooks-intro.html</a></li>\n<li><a href=\"https://reactjs.org/docs/context.html\">https://reactjs.org/docs/context.html</a></li>\n<li><a href=\"https://reactjs.org/docs/hooks-reference.html#usecontext\">https://reactjs.org/docs/hooks-reference.html#usecontext</a></li>\n</ul>\n<p>If you are ready, let's start right off the bet, by moving into the first step.</p>\n<h3 id=\"instruct-gatsby-to-create-a-separate-div-with-id-single-modal\" style=\"position:relative;\"><a href=\"#instruct-gatsby-to-create-a-separate-div-with-id-single-modal\" aria-label=\"instruct gatsby to create a separate div with id single modal permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Instruct Gatsby to create a separate div with id \"single-modal\"</h3>\n<p>By default, Gatsby renders each page under <code class=\"language-text\">&lt;div id=&quot;___gatsby&quot;&gt;</code> DOM element.</p>\n<p>The only way to add another div is to use the Gatsby <a href=\"https://www.gatsbyjs.org/docs/ssr-apis/\">Server Rendering APIs</a>. We are going to use <em>onRenderBody</em> method.</p>\n<p>Open the <strong>gatsby-ssr.js</strong> file and put in place following piece of code</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">onRenderBody</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> setPostBodyComponents <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n <span class=\"token function\">setPostBodyComponents</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token operator\">&lt;</span>div key<span class=\"token operator\">=</span><span class=\"token string\">\"single-modal\"</span> id<span class=\"token operator\">=</span><span class=\"token string\">\"single-modal\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> onRenderBody <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"extend-reactstrap-modal-to-render-his-content-inside-this-single-modal-element\" style=\"position:relative;\"><a href=\"#extend-reactstrap-modal-to-render-his-content-inside-this-single-modal-element\" aria-label=\"extend reactstrap modal to render his content inside this single modal element permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Extend Reactstrap Modal to render his content inside this \"single-modal\" element.</h3>\n<p>Reactstrap Modal offers no <em>prop</em> that can overwrite the DOM element it will render into. Fortunately, we can extend it and tweak a few parts in there.</p>\n<p>Create a file <strong>src/components/modal.js</strong> and put following piece in there</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Modal <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'reactstrap'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">SingleModal</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Modal</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>_element <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'single-modal'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>_element<span class=\"token punctuation\">.</span><span class=\"token function\">setAttribute</span><span class=\"token punctuation\">(</span><span class=\"token string\">'tabindex'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'-1'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>_element<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>position <span class=\"token operator\">=</span> <span class=\"token string\">'relative'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>_element<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>zIndex <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>zIndex<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>onExit<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span><span class=\"token function\">onExit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>_element<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">manageFocusAfterClose</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>isOpen<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">close</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>_isMounted <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> SingleModal <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>In the constructor, we grab the single-modal element and assign it to <em>_element</em> variable. By doing this, we opt-out from the default behavior of Reactstrap Modal. This means that Reactstrap will render his content inside our \"single-modal\" div.</p>\n<p>Reactstrap Modal comes with a handy <em>unmountOnClose</em> prop.  Whenever set to false, it will keep the Modal in the DOM.</p>\n<p>The only problem is that Modal's <em>componentWillUnmount</em> lifecycle method ignores <em>unmountOnClose</em> prop completely. And that is the reason to overwrite it by remove the destroy function call.</p>\n<p>I agree that going this route feels a bit like a hack. If you update Reactstrap, you must always double-check if everything works. If you have time to roll out your own Modal component, it will be definitely a better solution.</p>\n<h3 id=\"wrap-every-gatsby-page-inside-layout-component\" style=\"position:relative;\"><a href=\"#wrap-every-gatsby-page-inside-layout-component\" aria-label=\"wrap every gatsby page inside layout component permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wrap every Gatsby page inside Layout component</h3>\n<p>By default, Gatsby Starter Kit gives us Layout component and three pages. It's fine to use Layout at every page you create, but Gatsby comes with a handy <a href=\"https://www.gatsbyjs.org/docs/browser-apis/#wrapPageElement\">wrapPageElement Browser API</a> for that.</p>\n<p>Open <strong>gatsby-browser.js</strong> and paste following code in there</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Layout <span class=\"token keyword\">from</span> <span class=\"token string\">'./src/components/layout'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">wrapPageElement</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> element<span class=\"token punctuation\">,</span> props <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Layout</span></span> <span class=\"token spread\"><span class=\"token punctuation\">{</span><span class=\"token punctuation\">...</span><span class=\"token attr-value\">props</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">{</span>element<span class=\"token punctuation\">}</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">Layout</span></span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> wrapPageElement <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Having this, you can remove now the Layout dependency from <strong>src/pages/index.js</strong>, <strong>src/pages/404.js</strong> and <strong>src/pages/page-2</strong>.</p>\n<p>With this approach, even a dynamic page in Gatsby will have a wrapping Layout component. Pretty neat!</p>\n<h3 id=\"use-react-context-to-create-singlemodalprovider-and-usesinglemodal-custom-hook\" style=\"position:relative;\"><a href=\"#use-react-context-to-create-singlemodalprovider-and-usesinglemodal-custom-hook\" aria-label=\"use react context to create singlemodalprovider and usesinglemodal custom hook permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use React Context to create SingleModalProvider and useSingleModal custom hook</h3>\n<p>In here, we are going to touch the state management part. We want to allow every Component on every Page to have access to two variables.</p>\n<ul>\n<li>one for controlling the show/hide of the Modal</li>\n<li>one for displaying the content of the Modal</li>\n</ul>\n<p>We also want to allow to close, toggle and set the content of the modal. And for this we will need to expose some methods.</p>\n<p>React Context appears as a perfect solution here. We could use Redux or Mobx, but it doesn't matter. Feel free to experiment with it yourself.</p>\n<p>Let's start off by creating a <strong>src/contexts/SingleModalContext.js</strong> file with the following content.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> useState<span class=\"token punctuation\">,</span> useContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> SingleModalContext <span class=\"token operator\">=</span> React<span class=\"token punctuation\">.</span><span class=\"token function\">createContext</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useSingleModal</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> singleModalContext <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>SingleModalContext<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>singleModalContext<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'useSingleModal must be used inside the SingleModalProvider'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> singleModalContext<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">SingleModalProvider</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>showModal<span class=\"token punctuation\">,</span> setShowModal<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>modalContent<span class=\"token punctuation\">,</span> setModalContent<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">toggleModal</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setShowModal</span><span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>showModal<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">closeModal</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setShowModal</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">setContent</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setModalContent</span><span class=\"token punctuation\">(</span><span class=\"token function\">content</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> value <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    show<span class=\"token operator\">:</span> showModal<span class=\"token punctuation\">,</span>\n    toggle<span class=\"token operator\">:</span> toggleModal<span class=\"token punctuation\">,</span>\n    close<span class=\"token operator\">:</span> closeModal<span class=\"token punctuation\">,</span>\n    setContent<span class=\"token punctuation\">,</span>\n    content<span class=\"token operator\">:</span> modalContent<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">SingleModalContext.Provider</span></span> <span class=\"token attr-name\">value</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>value<span class=\"token punctuation\">}</span></span> <span class=\"token spread\"><span class=\"token punctuation\">{</span><span class=\"token punctuation\">...</span><span class=\"token attr-value\">props</span><span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> useSingleModal<span class=\"token punctuation\">,</span> SingleModalProvider <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>There are a few notable parts in there. We create the context first.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> SingleModalContext <span class=\"token operator\">=</span> React<span class=\"token punctuation\">.</span><span class=\"token function\">createContext</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Then, we build a Custom Hook called <em>useSingleModal</em> which uses the <em>SingleModalContext</em>.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useSingleModal</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> singleModalContext <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>SingleModalContext<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// ...</span>\n  <span class=\"token keyword\">return</span> singleModalContext<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Then we craft the <em>SingleModalProvider</em>, which will provide two variables and three functions.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">const</span> value <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  show<span class=\"token operator\">:</span> showModal<span class=\"token punctuation\">,</span>\n  toggle<span class=\"token operator\">:</span> toggleModal<span class=\"token punctuation\">,</span>\n  close<span class=\"token operator\">:</span> closeModal<span class=\"token punctuation\">,</span>\n  setContent<span class=\"token punctuation\">,</span>\n  content<span class=\"token operator\">:</span> modalContent<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">SingleModalContext.Provider</span></span> <span class=\"token attr-name\">value</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>value<span class=\"token punctuation\">}</span></span> <span class=\"token spread\"><span class=\"token punctuation\">{</span><span class=\"token punctuation\">...</span><span class=\"token attr-value\">props</span><span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The most interesting function is <em>setContent</em>. Its argument must be a Closure, which means it can accept the JSX syntax. This will allow to use <em>ModalBody</em>, <em>ModalHeader</em> and <em>ModalFooter</em> inside your Modal.</p>\n<h3 id=\"wrap-your-application-within-singlemodalprovider\" style=\"position:relative;\"><a href=\"#wrap-your-application-within-singlemodalprovider\" aria-label=\"wrap your application within singlemodalprovider permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wrap your application within SingleModalProvider</h3>\n<p>Also in here, Gatsby has us covered. It delivers the <a href=\"https://www.gatsbyjs.org/docs/browser-apis/#wrapRootElement\">wrapRootElement Browser API</a> and <a href=\"https://www.gatsbyjs.org/docs/ssr-apis/#wrapRootElement\">wrapRootElement SSR API</a></p>\n<p>Open <strong>gatsby-browser.js</strong> file and add the following</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> SingleModalProvider <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./src/contexts/SingleModalContext'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">wrapRootElement</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> element <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">SingleModalProvider</span></span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">{</span>element<span class=\"token punctuation\">}</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">SingleModalProvider</span></span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> wrapRootElement <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The exact same snippet must go inside <strong>gatsby-ssr.js</strong>, so please adjust it too.</p>\n<h3 id=\"render-extended-modal-at-the-bottom-of-the-layout-with-sane-defaults\" style=\"position:relative;\"><a href=\"#render-extended-modal-at-the-bottom-of-the-layout-with-sane-defaults\" aria-label=\"render extended modal at the bottom of the layout with sane defaults permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Render Extended Modal at the bottom of the Layout with sane defaults</h3>\n<p>At this point, we have a DOM element to render the Modal into. We have an overwritten Reactstrap Modal so it will mount there forever. We have also set up our state management with React Context. Our application uses <em>SingleModalProvider</em> and each Gatsby page makes usage of Layout component.</p>\n<p>The only part missing is to create the Single Modal itself. The best place for doing it is at the bottom of the Layout component. So open the <strong>src/components/layout.js</strong> and adjust it as shown below.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> SingleModal <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./modal'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> useSingleModal <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'../contexts/SingleModalContext'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Layout</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> children <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> show<span class=\"token punctuation\">,</span> toggle<span class=\"token punctuation\">,</span> content <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useSingleModal</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// ...</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span>\n        <span class=\"token attr-name\">style</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span>\n          margin<span class=\"token operator\">:</span> <span class=\"token string\">'0 auto'</span><span class=\"token punctuation\">,</span>\n          maxWidth<span class=\"token operator\">:</span> <span class=\"token number\">960</span><span class=\"token punctuation\">,</span>\n          padding<span class=\"token operator\">:</span> <span class=\"token string\">'0px 1.0875rem 1.45rem'</span><span class=\"token punctuation\">,</span>\n          paddingTop<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span></span>\n      <span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>main</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">{</span>children<span class=\"token punctuation\">}</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>main</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>footer</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">© </span><span class=\"token punctuation\">{</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getFullYear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span><span class=\"token plain-text\">, TekMi</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>footer</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">SingleModal</span></span> <span class=\"token attr-name\">isOpen</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>show<span class=\"token punctuation\">}</span></span> <span class=\"token attr-name\">toggle</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">toggle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span> <span class=\"token attr-name\">unmountOnClose</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n          </span><span class=\"token punctuation\">{</span>content<span class=\"token punctuation\">}</span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">SingleModal</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>In here, we first import our <em>SingleModal</em> and the <em>useSingleModal</em> Custom Hook.</p>\n<p>At the bottom of Layout render method, we add the <em>SingleModal</em> component. Important part here is the <em>unmountOnClose</em> prop set to false.</p>\n<p>Because our SingleModal is actually a Reactstrap Modal, it's controlled by isOpen prop and toggled with toggle prop.</p>\n<p>The content comes from React Context and is available to every Component on every Page.</p>\n<h3 id=\"call-the-modal-from-within-the-gatsby-page\" style=\"position:relative;\"><a href=\"#call-the-modal-from-within-the-gatsby-page\" aria-label=\"call the modal from within the gatsby page permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Call the Modal from within the Gatsby page</h3>\n<p>Having the Modal mounted inside the \"single-modal\" DOM element, let's invoke it from the Gatsby index page. Open the <strong>src/pages/index.js</strong> and adjust it as presented below.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'bootstrap/dist/css/bootstrap.min.css'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Button<span class=\"token punctuation\">,</span> ModalBody<span class=\"token punctuation\">,</span> ModalFooter<span class=\"token punctuation\">,</span> ModalHeader<span class=\"token punctuation\">,</span> ButtonGroup <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'reactstrap'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> useSingleModal <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'../contexts/SingleModalContext'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">IndexPage</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> toggle<span class=\"token punctuation\">,</span> close<span class=\"token punctuation\">,</span> setContent <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useSingleModal</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">toggleModalWithContent</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">cont</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setContent</span><span class=\"token punctuation\">(</span>cont<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">toggle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ButtonGroup</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Button</span></span> <span class=\"token attr-name\">color</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>info<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">onClick</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">toggleModalWithContent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token string\">'TekMi'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n          Open Modal\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">Button</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Button</span></span> <span class=\"token attr-name\">color</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>warning<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">onClick</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">toggleModalWithContent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token number\">11</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n          Open Number Modal\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">Button</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Button</span></span> <span class=\"token attr-name\">color</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>success<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">onClick</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">toggleModalWithContent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">[</span><span class=\"token number\">11</span><span class=\"token punctuation\">,</span> <span class=\"token number\">22</span><span class=\"token punctuation\">,</span> <span class=\"token number\">33</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n          Open Array Modal\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">Button</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Button</span></span>\n          <span class=\"token attr-name\">color</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>danger<span class=\"token punctuation\">\"</span></span>\n          <span class=\"token attr-name\">onClick</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n            <span class=\"token function\">toggleModalWithContent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n              <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n                <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                  </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ModalHeader</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Modal title</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">ModalHeader</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                  </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ModalBody</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Another Test</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">ModalBody</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                  </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ModalFooter</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Button</span></span> <span class=\"token attr-name\">color</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>primary<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">onClick</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">close</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                      Do Something\n                    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">Button</span></span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">{</span><span class=\"token string\">' '</span><span class=\"token punctuation\">}</span><span class=\"token plain-text\">\n                    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Button</span></span> <span class=\"token attr-name\">color</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>secondary<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">onClick</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">close</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                      Cancel\n                    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">Button</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                  </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">ModalFooter</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span></span><span class=\"token punctuation\">></span></span>\n              <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">}</span></span>\n        <span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n          Open JSX Modal\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">Button</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">ButtonGroup</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> IndexPage<span class=\"token punctuation\">;</span></code></pre></div>\n<p>First, we import the bootstrap styles and Reactstrap Modal Components.</p>\n<p>Then we import our <em>useSingleModal</em> Custom Hook and make use of it inside our local function <em>toggleModalWithContent</em>.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> toggle<span class=\"token punctuation\">,</span> close<span class=\"token punctuation\">,</span> setContent <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useSingleModal</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">toggleModalWithContent</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">cont</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">setContent</span><span class=\"token punctuation\">(</span>cont<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">toggle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>After this, we create several buttons that pass different content to our Single Modal. Please note that even JSX syntax is possible, making it a robust solution.</p>\n<hr>\n<p>Exercise: Feel free to click the buttons and examine DOM tree inside your Developer Tools at the same time. You will notice that each Modal content renders inside \"single-modal\" DOM element, no matter which button you clicked. Even when you close the Modal, its HTML stays untouched - the only thing that changes is its display to none.</p>\n<hr>\n<p>Looks like we have achieved what we wanted!</p>\n<p>Please study the accompanying <a href=\"https://github.com/tekmi/blogging-gatsby-modals\">Gatsby with Modals repository</a> to get a deeper understanding of this solution.</p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>This has been a lengthy tutorial. It touched several core concepts, including React Context, React Portal and React Hooks. It used a lot of Gatsby SSR and Browser APIs.</p>\n<p>It has demonstrated that it's possible to have only one DOM element and re-use it with the same Modal, swapping its content.</p>\n<p>It is an experimental implementation, so don't be too hasty to use it in your codebase. It may not work if you are in a more sophisticated situation, like Modals on top of Modals.</p>\n<p>If you see some Accessibility issues or a needless Re-renders, please let me know via Twitter.</p>\n<p>My next step is to verify how Single Modal is going to work with the Redux and Custom Redux Middleware. Soon after, I'm planning to create a custom Modal, which will make Reactstrap and hacks around it obsolete.</p>"}},"pageContext":{"postId":"7de24bf7-aaaa-593f-9ee1-33131e7c7c3b","slug":"how-to-create-single-modal-in-gatsby-using-reactstrap-react-portals-react-context-and-react-custom-hooks"}}}