UI development concepts
The genesys-catalog-ui shows how a SSR-enabled React app can be implemented and we introduced many workarounds to handle synchronization of SSR, state, navigation with the component. Here I document some concepts that should make it easier for consistent development of the Genesys Website.
Please comment on these ideas!
Implementing Genesys using JSPs showed that it would be best to implement all JSPs using a fixed set of custom UI components. That way the styles and structure of UI components could easily be modified in one place without having to check each page individually.
For consistent UI across the entire application we will build a library of GUI components in
src/gui/. This includes everything down to a
<Button. The components in this library will be pure and can rely only on
ownProps (no Redux state or actions).
This library will be built as we go (when missing) and we should aim to use these components whenever possible.
Composite components like
<Menu are part of this library.
Functional GUI components
Functional components (like
<Autocompleter) follow these concepts:
- They rely on
- Never use Redux
- Re-use custom layout components available in
src/gui/layout(or add them)
- Avoid importing from @material-ui and other libraries, reuse
src/gui/components (or add them)
- Avoid customized styles (they should come from
- They may use Redux actions that call API services, but must do so using
A good example is
ui/common/permission/Permissions.tsx which makes API calls, but does not have its state managed by a reducer.
Pages are the components that are linked to a route.
The route definitions document how the pages link into top-level groups. For example, looking at routes in the genesys-catalog-ui shows that PartnerBrowsePage, PartnerDisplayPage and PartnerEditPage belong together and can form one group. A group then has
reducers/partners.ts that maintains the state for these components.
Navigation to any Details page should be done with an action so that necessary API calls are made, data refreshed and then the route changed to render the associated route component.
All URL changes (including query string) should be managed by actions and never by a component directly.
SSR and blank state
Without SSR the page has no data in Redux store. If we use
undefined in reducer initial state we can detect it and trigger the
initXxxxPage action defined in
actions/partners.ts. The same method would be declared in
static needs for SSR and it will use parameters from the query string.