React: add HTML from generic file path at server-side build time

32
November 24, 2021, at 3:20 PM

The use case I'm trying to fulfill:

  1. Admin adds SVG along with new content in CMS, specifying in the CMS which svg goes with which content
  2. CMS commits change to git (Netlify CMS)
  3. Static site builds again
  4. SVG is added inline so that it can be styled and/or animated according to the component in which it occurs

Now - I can't figure out a clean way to add the SVG inline. My logic tells me - everything is available at build time (the svgs are in repo), so I should be able to simply inline the svgs. But I don't know how to generically tell React about an svg based on variables coming from the CMS content. I can import the svg directly using svgr/weback, but then I need to know the file name while coding, which I don't since it's coming from the CMS. I can load the svg using fs.readFileSync, but then the SVG gets lost when react executes client-side.

I added my current solution as an answer, but it's very hacky. Please tell me there's a better way to do this with react!

Answer 1

Here is my current solution, but it's randomly buggy in dev mode and doesn't seem to play well with next.js <Link /> prefetching (I still need to debug this):

I. Server-Side Rendering

  1. Read SVG file path from CMS data (Markdown files)
  2. Load SVG using fs.readFileSync()
  3. Sanitize and add the SVG in React

II. Client-Side Rendering

  1. Initial Get:/URL response contains the SVGs (ssr worked as intended)
  2. Read the SVGs out of the DOM using HTMLElement.outerHTML
  3. When React wants to render the SVG which it doesn't have, pass it the SVG from the DOM

Here is the code.


import reactParse from "html-react-parser";
import DOMPurify from "isomorphic-dompurify";
import * as fs from "fs";
const svgs = {}; // { urlPath: svgCode }
const createServerSide = (urlPath) => {
  let path = "./public" + urlPath;
  let svgCode = DOMPurify.sanitize(fs.readFileSync(path));
  // add id to find the SVG client-side
  // the Unique identifier is the filepath for the svg in the git repository
  svgCode = svgCode.replace("<svg", `<svg id="${urlPath}"`);
  svgs[urlPath] = svgCode;
};
const readClientSide = (urlPath) => {
  let svgElement = document.getElementById(urlPath);
  let svgCode = svgElement.outerHTML;
  svgs[urlPath] = svgCode;
};
const registerSVG = (urlPath) => {
  if (typeof window === "undefined") {
    createServerSide(urlPath);
  } else {
    readClientSide(urlPath);
  }
  return true;
};
const inlineSVGFromCMS = (urlPath) => {
  if (!svgs[urlPath]) {
    registerSVG(urlPath);
  }
  return reactParse(svgs[urlPath]);
};
export default inlineSVGFromCMS;
READ ALSO
PHP social contribution Yearly [closed]

PHP social contribution Yearly [closed]

Want to improve this question? Update the question so it focuses on one problem only by editing this post

39
Couchbase APIs, libraries or curl commands to copy data from one cluster to another

Couchbase APIs, libraries or curl commands to copy data from one cluster to another

I want to copy my data from one cluster of Couchbase to another cluster either via curl commands or using SDK librariesCould someone please let me know if is there any libraries/APIs available by which I can be do this

53
Returning a array of objects by reducing and array

Returning a array of objects by reducing and array

I'm trying to return an array of objects from an arraySo for example

31
Android java foreground service

Android java foreground service

foreground service keeps particular activity in background or whole app , Like am making an app which gets values from sensorand fetch location

32