-1

Im coding for a school project and they dropped this code, that is working fine. But they want us to bundle those javascript files into one file, using imports/exports. It looks EASY but it's NOT.

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Basic routing</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>

  <body>
    <a href="#">Home</a>
    <a href="#pagelist">PageList</a>
    <a href="#pagelist/borderlands">PageList borderlands</a>

    <section id="pageContent">Choisissez un lien</section>

    <script src="js/Home.js"></script>
    <script src="js/PageList.js"></script>
    <script src="js/PageDetail.js"></script>
    <script src="js/routes.js"></script>
    <script src="app.js"></script>

  // then i'll use <script src="./dist/bundle.js"></script>

  </body>
</html>

src/js/Home.js

const Home = (argument = "") => {
 console.log("Page List", argument);
};
export default Home

src/js/PageDetail.js

const PageDetail = (argument) => {
  const preparePage = () => {
    cleanedArgument = argument.replace(/\s+/g, "-");


    const fetchGame = (url, argument) => {
      let finalURL = url + argument;

      fetch(`${finalURL}`)
        .then((response) => response.json())
        .then((response) => {
          let { name, released, description } = response;

          let articleDOM = document.querySelector(".page-detail .article");

          articleDOM.querySelector("h1.title").innerHTML = name;
          articleDOM.querySelector("p.release-date span").innerHTML = released;
          articleDOM.querySelector("p.description").innerHTML = description;
        });
    };

    fetchGame(`https://api.rawg.io/api/games?key=4a7bd6f3d4314002babc4e422c08c2e6& ${cleanedArgument}`);
  };

  const render = () => {
    pageContent.innerHTML = `
      <section class="page-detail">
        <div class="article">
          <h1 class="title"></h1>
          <p class="release-date">Release date : <span></span></p>
          <p class="description"></p>
        </div>
      </section>
    `;

    preparePage();
  };

  render();
};
export default PageDetail

src/js/PageList.js

const PageList = (argument = "") => {
  const preparePage = () => {
    cleanedArgument = argument.replace(/\s+/g, "-");
    let articles = "";

    const fetchList = (url, argument) => {
      let finalURL = url;
      if (argument) {
        finalURL = url + "?search=" + argument;
      }

      fetch(`${finalURL}`)
        .then((response) => response.json())
        .then((response) => {
          response.results.forEach((article) => {
            articles += `
                  <div class="cardGame">
                    <h1>${article.name}</h1>
                    <h2>${article.released}</h2>
                    <a href = "#pagedetail/${article.id}">${article.id}</a>
                  </div>
                `;
          });
          document.querySelector(".page-list .articles").innerHTML = articles;
        });
    };

    fetchList(`https://api.rawg.io/api/games?key=4a7bd6f3d4314002babc4e422c08c2e6& ${cleanedArgument}`);
  };

  const render = () => {
    pageContent.innerHTML = `
      <section class="page-list">
        <div class="articles">...loading</div>
      </section>
    `;

    preparePage();
  };

  render();
};
export default PageList

src/js/routes.js

const routes = {
  "": Home,
  "pagelist": PageList,
  "pagedetail": PageDetail,
};
export default routes

src/js/index.js

import Home from './Home'
Home() // trying to invoke them one by one.. but it's not working 
import PageList from './PageList'
PageList() // 
import PageDetail from './PageDetail'
PageDetail() // 
import routes from './routes'
routes()

let pageArgument;

const setRoute = () => {
  let path = window.location.hash.substring(1).split("/");
  pageArgument = path[1] || "";

  var pageContent = document.getElementById("pageContent");
  routes[path[0]](pageArgument);
  return true;
};

window.addEventListener("hashchange", () => setRoute());
window.addEventListener("DOMContentLoaded", () => setRoute());

Now if I take all the code from all the files and put them in one file. It works. But i don't understand how to do and why it's so hard for something thats looks really easy.

in-one-file, its working but I must use imports/exports, so I cannot use that !

const Home = (argument = "") => {
  console.log("Batman", argument);
};

const PageDetail = (argument) => {
  const preparePage = () => {
    cleanedArgument = argument.replace(/\s+/g, "-");


    const fetchGame = (url, argument) => {
      let finalURL = url + argument;

      fetch(`${finalURL}`)
        .then((response) => response.json())
        .then((response) => {
          let { name, released, description } = response;

          let articleDOM = document.querySelector(".page-detail .article");

          articleDOM.querySelector("h1.title").innerHTML = name;
          articleDOM.querySelector("p.release-date span").innerHTML = released;
          articleDOM.querySelector("p.description").innerHTML = description;
        });
    };

    fetchGame(`https://api.rawg.io/api/games?key=4a7bd6f3d4314002babc4e422c08c2e6& ${cleanedArgument}`);
  };

  const render = () => {
    pageContent.innerHTML = `
      <section class="page-detail">
        <div class="article">
          <h1 class="title"></h1>
          <p class="release-date">Release date : <span></span></p>
          <p class="description"></p>
        </div>
      </section>
    `;

    preparePage();
  };

  render();
};

const PageList = (argument = "") => {
  const preparePage = () => {
    cleanedArgument = argument.replace(/\s+/g, "-");
    let articles = "";

    const fetchList = (url, argument) => {
      let finalURL = url;
      if (argument) {
        finalURL = url + "?search=" + argument;
      }

      fetch(`${finalURL}`)
        .then((response) => response.json())
        .then((response) => {
          response.results.forEach((article) => {
            articles += `
                  <div class="cardGame">
                    <h1>${article.name}</h1>
                    <h2>${article.released}</h2>
                    <a href = "#pagedetail/${article.id}">${article.id}</a>
                  </div>
                `;
          });
          document.querySelector(".page-list .articles").innerHTML = articles;
        });
    };

    fetchList(`https://api.rawg.io/api/games?key=4a7bd6f3d4314002babc4e422c08c2e6& ${cleanedArgument}`);
  };

  const render = () => {
    pageContent.innerHTML = `
      <section class="page-list">
        <div class="articles">...loading</div>
      </section>
    `;

    preparePage();
  };

  render();
};

const routes = {
  "": Home,
  "pagelist": PageList,
  "pagedetail": PageDetail,
};

let pageArgument;

const setRoute = () => {
  let path = window.location.hash.substring(1).split("/");
  pageArgument = path[1] || "";

  var pageContent = document.getElementById("pageContent");
  routes[path[0]](pageArgument);
  return true;
};

window.addEventListener("hashchange", () => setRoute());
window.addEventListener("DOMContentLoaded", () => setRoute());
pedrofromperu
  • 95
  • 1
  • 9

1 Answers1

1

Your combined file and your individual files clearly contain different code: In src/js/index.js you are calling Home and claim it doesn't work. In the single file you are not calling Home. So why do you call Home?

Home, PageList and PageDetail are not needed in src/js/index.js. They are used in src/js/routes.js, so that's where they should be imported:

import Home from './Home'
import PageList from './PageList'
import PageDetail from './PageDetail'

const routes = {
  "": Home,
  "pagelist": PageList,
  "pagedetail": PageDetail,
};
export default routes

routes is required in src/js/index.js but you don't need to call it (and can't because it's not a function, it's an object). It's accessed further below routes[path[0]](pageArgument);. So all you have to do is import it:

import routes from './routes'

let pageArgument;
...

It's not clear what you do with your HTML, but you'd either only include the index.js file as a module or you would include the bundle file, but certainly not all files individually.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Thanks for answering. It says "Home is not defined" now. I think I should export my Home into PageList & PageDetail, but then I know I'll face more errors ( I've tried already ). – pedrofromperu Jul 28 '21 at 21:58
  • Where is the error thrown? You are not referencing `Home` anywhere else. *" I think I should export my Home into PageList & PageDetail"* Why do you think that? Are you accessing `Home` there? – Felix Kling Jul 28 '21 at 22:00
  • routes.js:3 Uncaught ReferenceError: Home is not defined at routes.js:3 I'll try to export PageList & PageDetail there, then more errors coming for sure I've tried that already. Sorry if I seem arsh or lame, Im new and have never been struggling like this before. – pedrofromperu Jul 28 '21 at 22:02
  • See my update to the question. Without knowing how/when/where the file `routes.js` is processed I can only guess. If you haven't added the `import` statements to `routes.js` then do that because that's part of the fix. – Felix Kling Jul 28 '21 at 22:04
  • Aight i've reach back that point where the error message is too big for me to handle. ''' Uncaught ReferenceError: cleanedArgument is not defined at preparePage (PageList.js:5) at render (PageList.js:40) at Object.PageList [as pagelist] (PageList.js:43) at setRoute (app.js:27) at app.js:33 ''' – pedrofromperu Jul 28 '21 at 22:09
  • You forgot to declare `cleanedArguments`. It should be `const cleanedArguments = ...` at the beginning of those functions (i.e. add `const`). Modules are always *strict*, so any variable has to be declared. – Felix Kling Jul 28 '21 at 22:27