{"componentChunkName":"component---src-templates-blog-post-js","path":"/blog/2019/07/netlify-cms-gatsby-plugin-4-0-0","result":{"data":{"site":{"siteMetadata":{"siteUrl":"https://www.netlifycms.org"}},"markdownRemark":{"frontmatter":{"title":"React Hooks support in Netlify CMS (and the Gatsby plugin)","description":"Netlify CMS 2.9.0 allows React Hooks to be used in custom Netlify CMS previews and widgets, and `gatsby-plugin-netlify-cms` 4.0.0 extends that support to Gatsby projects.","date":"July 23, 2019","author":"Tony Alves","twitter_image":null,"canonical_url":null},"html":"<p>Netlify CMS is an extensible app written in, and bundled with, React. The most common extension is the custom preview template, which allows the preview on the right side of the editor to show what the site will actually look like as you type. These preview templates are also written in React.</p>\n<p>Preview templates and other extensions can only use the Netlify CMS bundled copy of React via the <code>createClass()</code> method that Netlify CMS exports. Since React components are most often written in JSX and transpiled through a build system, most developers won't want to use this method, so the preview templates are created with a separate copy of React.</p>\n<p><strong>This means that Netlify CMS has two instances of React running at once.</strong></p>\n<p>But everything still worked - until React Hooks was released.</p>\n<h2 id=\"the-problem-react-hooks\" style=\"position:relative;\"><a href=\"#the-problem-react-hooks\" aria-label=\"the problem react hooks 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>The problem: React Hooks</h2>\n<p>Before <a href=\"https://reactjs.org/docs/hooks-intro\" target=\"_blank\" rel=\"noopener noreferrer\">Hooks</a>, multiple instances of React <em>could</em> work on the same DOM, although it was warned against and technically not supported. React Hooks <a href=\"https://reactjs.org/warnings/invalid-hook-call-warning#duplicate-react\" target=\"_blank\" rel=\"noopener noreferrer\">changed this</a> by throwing an error if multiple instances are detected. When developers started using hooks in their Netlify CMS previews and widgets, their applications stopped working 😭</p>\n<h2 id=\"the-solution-netlify-cms-app\" style=\"position:relative;\"><a href=\"#the-solution-netlify-cms-app\" aria-label=\"the solution netlify cms app 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>The solution: <code>netlify-cms-app</code></h2>\n<p>In the past, the <code>netlify-cms</code> npm package was the only way to run Netlify CMS - it's a \"batteries included\" distribution that runs as-is, bringing along React and a number of default extensions (widgets, backends, etc).</p>\n<p>As of Netlify CMS 2.9.0, a new <code>netlify-cms-app</code> package is provided as a slimmed down alternative to <code>netlify-cms</code>. It still includes most default extensions, but excludes some of the heavier ones, like media libraries for external providers.</p>\n<p>Most importantly, <strong>it does not include <code>react</code> or <code>react-dom</code></strong>, requiring them instead as <a href=\"https://nodejs.org/es/blog/npm/peer-dependencies/\" target=\"_blank\" rel=\"noopener noreferrer\">peer dependencies</a>. This allows Netlify CMS and any extensions to all use a single instance of React and React DOM. As a bonus, the <code>netlify-cms-app</code> bundle is a bit smaller than <code>netlify-cms</code>.</p>\n<h2 id=\"how-to-use-it\" style=\"position:relative;\"><a href=\"#how-to-use-it\" aria-label=\"how to use it 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>How to use it</h2>\n<p><strong>If you're building your site with Gatsby, skip this section.</strong> For all others, you'll want to:</p>\n<ol>\n<li>Uninstall <code>netlify-cms</code> if you're already using it</li>\n<li>Install <code>netlify-cms-app</code></li>\n<li>Install <code>react</code> and <code>react-dom</code></li>\n<li>Optionally install and register media libraries (see below).</li>\n</ol>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> uninstall netlify-cms\n<span class=\"token function\">npm</span> <span class=\"token function\">install</span> netlify-cms-app react react-dom</code></pre></div>\n<p>That's it! Now Netlify CMS will use the version of React that you provide.</p>\n<h2 id=\"the-gatsby-plugin\" style=\"position:relative;\"><a href=\"#the-gatsby-plugin\" aria-label=\"the gatsby plugin 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>The Gatsby plugin</h2>\n<p>Gatsby provides transpiling and bundling with Babel and Webpack, and accepts plugins to support various JavaScript dialects, e.g., TypeScript. If a developer sets up their Gatsby site to be written a certain way, they'll want any CMS customization code to be written the same way. The problem is that Netlify CMS is a standalone app that would typically live in Gatsby's <code>static</code> directory, and Gatsby doesn't really have a way to handle a secondary entry point for the CMS for outputting a dedicated bundle.</p>\n<p>For this reason, we support an official Gatsby plugin, <a href=\"https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-netlify-cms\" target=\"_blank\" rel=\"noopener noreferrer\"><code>gatsby-plugin-netlify-cms</code></a>, which bundles preview templates and other Netlify CMS extensions using the same Babel and Webpack configuration as the Gatsby site itself.</p>\n<h2 id=\"using-react-hooks-with-netlify-cms-and-gatsby\" style=\"position:relative;\"><a href=\"#using-react-hooks-with-netlify-cms-and-gatsby\" aria-label=\"using react hooks with netlify cms and gatsby 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>Using React Hooks with Netlify CMS and Gatsby</h2>\n<p>The recent 4.0.0 release of <code>gatsby-plugin-netlify-cms</code> is the first to use <code>netlify-cms-app</code> and enable the use of React Hooks in Netlify CMS previews/widgets for Gatsby projects.</p>\n<p>If you want to start a new site now, or would like to see an example, check out <a href=\"https://github.com/netlify-templates/gatsby-starter-netlify-cms#gatsby--netlify-cms-starter\" target=\"_blank\" rel=\"noopener noreferrer\"><code>gatsby-starter-netlify-cms</code></a> - it provides a great starting point and implements all of the remaining steps in this post.</p>\n<p>You can deploy it to Netlify right now with one click!</p>\n<p><a href=\"https://app.netlify.com/start/deploy?repository=https://github.com/netlify-templates/gatsby-starter-netlify-cms&#x26;stack=cms\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"https://www.netlify.com/img/deploy/button.svg\" alt=\"Deploy to Netlify\"></a></p>\n<h3 id=\"upgrading-an-existing-project\" style=\"position:relative;\"><a href=\"#upgrading-an-existing-project\" aria-label=\"upgrading an existing project 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>Upgrading an existing project</h3>\n<p>If you're already using <code>gatsby-plugin-netlify-cms</code>, you'll want to:</p>\n<ol>\n<li>Upgrade to 4.0.0 or newer</li>\n<li>Remove the <code>netlify-cms</code> dependency</li>\n<li>Add <code>netlify-cms-app</code></li>\n</ol>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> upgrade gatsby-plugin-netlify-cms@^4.0.0\n<span class=\"token function\">npm</span> uninstall netlify-cms\n<span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save netlify-cms-app</code></pre></div>\n<p>Note that you'll already have React and React DOM installed in your Gatsby project, so no need to do that here.</p>\n<h3 id=\"adding-to-a-new-project\" style=\"position:relative;\"><a href=\"#adding-to-a-new-project\" aria-label=\"adding to a new project 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>Adding to a new project</h3>\n<p>If you're <strong>not</strong> already using <code>gatsby-plugin-netlify-cms</code> with your Gatsby project, you can install it and <code>netlify-cms-app</code> via npm (or your package manager of choice):</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save netlify-cms-app gatsby-plugin-netlify-cms</code></pre></div>\n<p>You'll also need to register the plugin in <code>gatsby-config.js</code> in the site root. Create that file if it’s not already there, and add the following to register the Netlify CMS plugin:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// gatsby-config.js</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  plugins<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">gatsby-plugin-netlify-cms</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>The plugin will create the Netlify CMS app and output it to <code>/admin/index.html</code> on your site. The CMS will look for your configuration to be in the same directory on your live site, at <code>/admin/config.yml</code>, so you’ll want to place the configuration file in the <code>static</code> directory of your repo at <code>static/admin/config.yml</code>. You can also <a href=\"https://www.netlifycms.org/docs/beta-features/#manual-initialization\" target=\"_blank\" rel=\"noopener noreferrer\">configure Netlify CMS with JavaScript</a>. Read more about configuring the CMS in our docs, or check out the Gatsby / Netlify CMS integration guides in both our docs and theirs.</p>\n<ul>\n<li><a href=\"https://www.netlifycms.org/docs/add-to-your-site/#configuration\" target=\"_blank\" rel=\"noopener noreferrer\">Netlify CMS Configuration Guide</a></li>\n<li><a href=\"https://www.netlifycms.org/docs/gatsby/\" target=\"_blank\" rel=\"noopener noreferrer\">Netlify CMS Integration Guide for Gatsby Sites</a></li>\n<li><a href=\"https://www.gatsbyjs.org/docs/sourcing-from-netlify-cms/\" target=\"_blank\" rel=\"noopener noreferrer\">Gatsby Guide - Sourcing from Netlify CMS</a></li>\n</ul>\n<h2 id=\"using-media-libraries-with-netlify-cms-app\" style=\"position:relative;\"><a href=\"#using-media-libraries-with-netlify-cms-app\" aria-label=\"using media libraries with netlify cms app 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>Using Media Libraries with <code>netlify-cms-app</code></h2>\n<p>The Netlify CMS media library extensions for Cloudinary and Uploadcare are not included in <code>netlify-cms-app</code>. If you're using <code>netlify-cms-app</code>, you'll need to register media libraries yourself.</p>\n<p><strong>Note:</strong> if you're using <code>gatsby-starter-netlify-cms</code>, the media libraries are registered within the starter itself.</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 constant\">CMS</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'netlify-cms-app'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// You only need to import the media library that you'll use. We register both</span>\n<span class=\"token comment\">// here for example purposes.</span>\n<span class=\"token keyword\">import</span> uploadcare <span class=\"token keyword\">from</span> <span class=\"token string\">'netlify-cms-media-library-uploadcare'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> cloudinary <span class=\"token keyword\">from</span> <span class=\"token string\">'netlify-cms-media-library-cloudinary'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token constant\">CMS</span><span class=\"token punctuation\">.</span><span class=\"token function\">registerMediaLibrary</span><span class=\"token punctuation\">(</span>uploadcare<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token constant\">CMS</span><span class=\"token punctuation\">.</span><span class=\"token function\">registerMediaLibrary</span><span class=\"token punctuation\">(</span>cloudinary<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>For more information about the media libraries, refer to the docs.</p>\n<ul>\n<li><a href=\"https://www.netlifycms.org/docs/cloudinary/\" target=\"_blank\" rel=\"noopener noreferrer\">Using Cloudinary with Netlify CMS</a></li>\n<li><a href=\"https://www.netlifycms.org/docs/uploadcare/\" target=\"_blank\" rel=\"noopener noreferrer\">Using Uploadcare with Netlify CMS</a></li>\n</ul>\n<h3 id=\"with-gatsby-plugin-netlify-cms400\" style=\"position:relative;\"><a href=\"#with-gatsby-plugin-netlify-cms400\" aria-label=\"with gatsby plugin netlify cms400 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>With <code>gatsby-plugin-netlify-cms@^4.0.0</code></h3>\n<p>In addition to calling <code>registerMediaLibrary()</code> as mentioned above, make sure to provide the path to your CMS customization entry point to Gatsby via <code>gatsby-config.js</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// gatsby-config.js</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  plugins<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      resolve<span class=\"token operator\">:</span> <span class=\"token string\">'gatsby-plugin-netlify-cms'</span><span class=\"token punctuation\">,</span>\n      options<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        modulePath<span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>__dirname<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">/src/cms/cms.js</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</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>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>If you run into a problem or need help, <a href=\"https://github.com/netlify/netlify-cms/issues/new/choose\" target=\"_blank\" rel=\"noopener noreferrer\">open an issue on GitHub</a> or <a href=\"https://netlifycms.org/chat\" target=\"_blank\" rel=\"noopener noreferrer\">chat with our community</a>!</p>"}},"pageContext":{"slug":"/blog/2019/07/netlify-cms-gatsby-plugin-4-0-0"}}}