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!
GUI components
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 <ButtonBar
or <Menu
are part of this library.
Functional GUI components
Functional components (like <Autocompleter
) follow these concepts:
- They rely on
ownProps
- Never use Redux
state
- 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
src/gui/
components) - They may use Redux actions that call API services, but must do so using
bindActionCreators
(for authentication)
A good example is ui/common/permission/Permissions.tsx
which makes API calls, but does not have its state managed by a reducer.
Pages
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 actions/partners.ts
and 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.