-
Notifications
You must be signed in to change notification settings - 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
/Consumer
approach and theuseContext
hook) often used between different stages of the 'Flows' - we also make use of 'browser history state' to pass a specific
ProductDetail
into 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 '
is
predicate 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
before
andafter
when 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. ➡️