-
Couldn't load subscription status.
- Fork 4
Client side
manage-frontend client-side is primarily a single page React app, but with 'client-side routing' and some minimal 'server-side-rendering'.
It makes lots of AJAX/Async API calls to various different services (the vast majority of which are proxied via the node backend with the exception of the Identity tabs which go direct to identity APIs).
In manage-frontend we have so far managed to avoid the need for complex state management frameworks like Redux. Instead, getting by with a combination of...
- standard react state (both older style class based components and newer style hooks) with prop drilling
- when needing to make bigger leaps across the React component tree we use React Contexts (mixture of component/JSX
Provider/Consumerapproach and theuseContexthook) often used between different stages of the 'Flows' - we also make use of 'browser history state' to pass a specific
ProductDetailinto the 'Flows' (to avoid unnecessary re-fetching of that information).
As with the entire codebase we use TypeScript.
You will observe a convention for defining the shape of props and state with interfaces of the same name as the component plus Props or State respectively (e.g. MyStatefulComponent will have interfaces defined somewhere near called MyStatefulComponentProps and MyStatefulComponentState).
Notable TypeScript features that you will see used a fair bit are...
- 'optional chaining'
- the beautiful '
ispredicate functions' which mean we can write functions which not only allow us define our own conditions to confirm if the parameter adheres to a particular type/interface but also performs an implicit cast on the variable(s) in question on subsequent usages, for example given this function...function hasContactId( productDetail: ProductDetail ): productDetail is ProductDetailWithContactId { return !!productDetail.subscription.contactId; }
- notice the different types on
beforeandafterwhen using the above function (givenproductDetail:ProductDetail)...const before: string | undefined = productDetail.subscription.contactId; if( hasContactId(productDetail) ){ const after: string = productDetail.subscription.contactId; // because productDetail has been cast to ProductDetailWithContactId }
- this works really nicely with in-built functions like
filter...const before: ProductDetail[] = []; // imagine this was full of ProductDetail (some of which had .subscription.contactId defined) const after: ProductDetailWithContactId[] = before.filter( hasContactId ) // notice the array is now an array of ProductDetailWithContactId
- notice the different types on
manage-frontend takes a 'styled components' approach to CSS achieved with Emotion.
Standard HTML react components all accept a css attribute, and we use a blend of 'object style' and 'literal style', see...
| object style | literal style | |
|---|---|---|
| Example | <div css={textAlign: "right"}></div> |
<div css={css`text-align: right`}></div> |
| Benefits |
|
|
... we've not yet found a need to standardise on one approach (as they're both straight-forward) so it's personal preference currently.
There is one exception to this styling approach; in the 'Holiday Stops Flow' where we had to use raw-loader to use the css file from the date picker library.
Not what you're looking for? Be sure to use the navigation sidebar on the right. ➡️