Can you use a constant in place of the module path when using '"import obj from "../modulePath"'? (React)

Viewed 22

I'd like to import an array called "content" from one of several different files. I'd like to set which module to pull from based on a const I create (pageName), which titles the page in the PageTitle component. I'll concatenate this to "modulePath" which is located in a directory outside my components folder. But I'm having trouble with importing content when I reference the module path as a constant.

import React from "react"
import PageTitle from "./PageTitle"
import BuildItems from "./BuildItems"

function camelize(str) {
      return str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function (match, index) {
      if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
      return index === 0 ? match.toLowerCase() : match.toUpperCase();
    });
}
const pageName = "Settings";
const modulePath = "../" + camelize(pageName);
import content from modulePath;

function View() {
    return (
        <div className="View">
            <PageTitle content={pageName} layout="mini" />
            {content.map(BuildItems)}
        </div>
    );
}

export default View;

src folder structure is as follows:

src/
  components/
    App.js
    BuildItems.js
    PageTitle.js
    View.js
index.js
settings.js

It works fine when I replace import content from modulePath with import content from "../settings". But I'm wishing to do this dynamically by changing the const pageName to anything else (essentially switching out content).

1 Answers

Top-level imports must be static strings known at compile time. For your use case, you should use a dynamic import instead (await import(...)):

import React from "react"
import PageTitle from "./PageTitle"
import BuildItems from "./BuildItems"

function camelize(str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function (match, index) {
    if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
    return index === 0 ? match.toLowerCase() : match.toUpperCase();
  });
}
const pageName = "Settings";
const modulePath = "../" + camelize(pageName);

function View() {
  const [content, setContent] = useState(null);

  useEffect(() => {
    (async () => {
      // using the `await import(modulePath)` syntax to import a path based on a variable
      setContent(await import(modulePath))
    })();
  }, [])
  

  if (content === null) {
    return <div>Loading...</div>
  }

  function load() {
    <PageTitle content={pageName} layout="mini" />
    return content.map(BuildItems);
  }
  return (
    <div className="View">
      {load()}
    </div>
  );
}

export default View;
Related