2. Routing enums web #
Created Sat Dec 30, 2023 at 6:14 PM
Why enums #
Using literal values for navigation code is a bad idea, because:
- There’s scope for typos
- Even if there are no typos, one has to do “complete” testing to make sure everything works
- Refactoring is hard in the future.
- No auto-complete, too many manual lookups. Also, scope for error.
So, in addition to route markup (of navigators and screens), one should maintain a large POJO of just literals. And use this enum in navigation and initialRoute props.
About nesting #
Nesting isn’t an issue in web In a routes enum structure, there are 3 goals - uniqueness of keys, minimize manual lookup and ease of use in app code.
- For uniqueness - I mean uniqueness of navigable entities (pages). create a linear object with keys and values identical. or Better, create variables one below the other, with name and value identical. In both cases, the editor will let you know about duplicates.
- Minimize manual lookup: first of all, what lookups are we talking about in a route structure? Parent and children are two possibilities right. Then there’s self representation. And also, it’s the web and path sections matter, so we should represent structure in such a way that we don’t have to manipulate/concatenate stuff in the app code.
- We’ll use a single word (no
/
) key for a page or navigation link (like sidebar). We’ll name the keypathName
(not path, since path may indicate multiple words). This way, React Router local path is easy to specify (it is a single word). - Full path to the page. We’ll store it here itself. As
absolutePath
. This makes programmatic navigation easy.ROUTES.x.y.....absolutePath
- The value of this key will be an object as we’ll be creating an object here (2 pieces of data already). So keys are
pathName
,absolutePath
. - Store subpages (for navigation link) - as an object directory, follow same structure inside if there is a sub navigation link.
base
key - Additionally if the entity is a navigation link, add abase
string, and specifypathName
andabsolutePath
for use ininitialRouteName
in the markup. So if base changes, we only have to change this enum file. Don’t usebase
in app code.base
key - for simple single pages, this key should be absent. Appearing/not-appearing in auto-complete is also helpful to check if current path is a simple screen or not. Lookup avoided.
- We’ll use a single word (no
- Ease of usage - for usage with autocompletion we need an object (array won’t do), so make the exported structure is a single object, and it uses the unique keys we created.
Example:
const PUBLIC = '/public'; // top level ones have /
const PRIVATE = '/private';
const WELCOME = '/welcome';
const LOGIN = '/login'; // top level ones have /
const FORGOT_PASSWORD = '/forgot-password'; // top level ones have /
const CARS_BASE_ROUTE = "/cars";
const PHYSICAL_CARS_PATH_NAME = "physical-cars"; // middle words, no /
const VIRTUAL_CARS_PATH_NAME = "virtual-cars";
export const ROUTES = {
private: {
pathName: [PRIVATE],
absolutePath: `${PRIVATE}`,
cars: {
pathName: [CARS_BASE_ROUTE],
absolutePath: `${PRIVATE}/${CARS_BASE_ROUTE}`,
physicalCars: {
pathName: [PHYSICAL_CARS_PATH_NAME],
absolutePath: `${PRIVATE}/${CARS_BASE_ROUTE}/${PHYSICAL_CARS_PATH_NAME}`,
},
virtualCars: {
pathName: [VIRTUAL_CARS_PATH_NAME],
absolutePath: `${PRIVATE}/${CARS_BASE_ROUTE}/${VIRTUAL_CARS_PATH_NAME}`,
}
}
},
public: {
pathName: [PUBLIC],
absolutePath: `${PUBLIC}`,
base: { // this will be used to represent preferred route in markup
pathName: [WELCOME],
absolutePath: `${PUBLIC}/${WELCOME}`,
},
welcome: {
pathName: [WELCOME],
absolutePath: `${PUBLIC}/${WELCOME}`,
},
login: {
pathName: [LOGIN],
absolutePath: `${PUBLIC}/${LOGIN}`,
},
forgotPassword: {
pathName: [FORGOT_PASSWORD],
absolutePath: `${PUBLIC}/${FORGOT_PASSWORD}`,
}
}
}
<Route>
<Route
path={ROUTES.private.cars.absolutePath}
element={<MainApp />}
>
<Route
path={ROUTES.private.cars.physicalCars.pathName}
element={<PhysicalCars />}
/>
<Route
path={ROUTES.private.cars.virtualCars.pathName}
element={<VirtualCars />}
/>
</Route>
</Route>