I'm attempting to organize my routes file into multiple files but cannot access an "enum" object declared in the primary file due it not having been declared yet.
In the example below, I get the error ReferenceError: Cannot access 'MenuItem' before initialization.
I thought it was strange that the function (createRoute) does not cause the same error, so it does get declared before the routesSettings file calls it.
Is there any trick that would allow me to keep the structure I'm aiming for?
routes.js
import Home from "../pages/Home";
import Settings from "../pages/settings";
import { routesSettings } from "./routesSettings"
export const MenuItem = Object.freeze({
HOME: "Home",
SETTINGS: "Settings",
});
export const routes = [
// Home
createRoute(MenuItem.HOME, "/", Home),
// Settings
createRoute(MenuItem.SETTINGS, "/", SETTINGS),
...routesSettings,
]
export function createRoute(name, route, component) {
return { name, route, component };
}
routesSettings.js
import PasswordSettings from "../pages/settings/password";
import UserSettings from "../pages/settings/user";
import { createRoute, MenuItem } from "./routes"
export const routesSettings = [
createRoute(MenuItem.SETTINGS_PASSWORD, "/settings/password", PasswordSettings),
createRoute(MenuItem.SETTINGS_USER, "/settings/password", UserSettings),
];
The reason you are see this error: ReferenceError: Cannot access 'MenuItem' before initialization
is because you imported MenuItem in your routesSettings.js file; typically during compile time the JS engine will hoist all variable declarations in your lexical environment with undefined and they all remain uninitialized and only only gets initialized during the actual evaluation of the code.
Try console logging MenuItems in your routesSettings.js file, you'll see that it's value it's actually undefined in that file?
However, you'll notice that createRoute function didn't throw any errors...the reason is because function declarations in JS are added to the memory during compile which we can use before the actual function's declaration.
Typically, the JS engine looks into the lexical environment where it finds the function and executes it.
Also, if you change your createRoute function to:
export const createRoute = (name, route, component) => {
return { name, route, component };
};
you'll have errors like createRoute is undefined etc.. because const remain uninitialized, hence undefined in your lexical environment. Function expressions aren't hoisted either const neverHoisted = function(){...}.
In summary, JS only hoist declarations and not assignments/initializations.
What you need to do solve the issues you are seeing is to create a separate file for menuItem and import it in router.js and routeSettings.js files.