Electrode doesn't show dynamic data in page source

89 Views Asked by At

Using electrode, I noticed this weird behaviour -

When I view the page source after the page fully loads with all the api calls and data, I am only able to view the content that is static for example, the hyper links, headings, footer links etc.

I have created a custom token handler which checks the context object and populates the custom tokens present in the index.html. So, whenever, I console.log(context.user.content), only the data that is static such as hyperlinks, headings, footer links are logged.

I guess this is the problem but I am not able to wrap my head around as to why electrode doesn't recognise the content being rendered dynamically.

Token-Handler.js file

import Helmet from 'react-helmet';

const emptyTitleRegex = /<title[^>]*><\/title>/;

module.exports = function setup(options) {
  // console.log({ options });
  return {
    INITIALIZE: context => {
      context.user.helmet = Helmet.renderStatic();
    },
    PAGE_TITLE: context => {
      const helmet = context.user.helmet;
      const helmetTitleScript = helmet.title.toString();
      const helmetTitleEmpty = helmetTitleScript.match(emptyTitleRegex);

      return helmetTitleEmpty ? `<title>${options.routeOptions.pageTitle}</title>` : helmetTitleScript;
    },
    REACT_HELMET_SCRIPTS: context => {
      const scriptsFromHelmet = ["link", "style", "script", "noscript"]
        .map(tagName => context.user.helmet[tagName].toString())
        .join("");
      return `<!--scripts from helmet-->${scriptsFromHelmet}`;
    },
    META_TAGS: context => {
      console.log(context,'123') //this is where I am checking
      return context.user.helmet.meta.toString();
    }
  };
};

default.js

module.exports = {
  port: portFromEnv() || "3000",
  webapp: {
    module: "electrode-react-webapp/lib/express",
    options: {
      prodBundleBase: '/buy-used-car/js/',
      insertTokenIds: false,
      htmlFile: "./{{env.APP_SRC_DIR}}/client/index.html",
      paths: {
        "*": {
          content: {
            module: "./{{env.APP_SRC_DIR}}/server/views/index-view"
          },
        }
      },
      serverSideRendering: true,
      tokenHandler: "./{{env.APP_SRC_DIR}}/server/token-handler"
    }
  }
};

Any clue anyone?

EDIT 1

However, any following updates that occur on the meta tags are rendered. I'm not sure that is something electrode allows or is a feature of react-helmet.

EDIT 2

SSR is enabled in electrode.

1

There are 1 best solutions below

0
On

After digging in the docs, realised that there was a slight misunderstanding. So, if data needs to be present in the page source, it needs to be pre-rendered by the server.

Why it wasn't showing at the time I asked the question? Because, data was being evaluated at run-time due ot which the page source only rendered the static content.

Electrode already provides an abstraction, each component that is being rendered has an option to load with pre-fetched data. The catch here is, you have to evaluate what all data needs to be present at runtime because more data is directly proportional to page loading time (as the server won't resolve unless the api you are depending on returns you with either a success or failure )

In terms of implementation, each route has a parameter called init-top which is executed before your page loads.

const routes = [
  {
    path: "/",
    component: withRouter(Root),
    init: "./init-top",
    routes: [
      {
        path: "/",
        exact: true,
        component: Home,
        init: "./init-home"
      },

in init-home, you can define it something on the lines of -

import reducer from "../../client/reducers";
const initNumber = async () => {
  const value = await new Promise(resolve => setTimeout(() => resolve(123), 2000));
  return { value };
};
export default async function initTop() {
  return {
    reducer,
    initialState: {
      checkBox: { checked: false },
      number: await initNumber(),
      username: { value: "" },
      textarea: { value: "" },
      selectedOption: { value: "0-13" }
    }
  };
}

So,now whenever you load the component, it is loaded with this initialState returned in init-home

I'll just post it here, in case anyone is stuck.