Skip to main content

UI components

Below are some guidelines for deciding how to organise your components in your frontend projects.

There is a relation to implementing proper state management. Ideally you should be able to re-shuffle your components, pages and routing at will without having to touch your logic or change your data structures.

Pages#

Pages are used as targets for routes. They should have a minimal amount of code in them. They will declare their layout in high level components. So things like toolbar, sidebar, main list component.

CHECK: if the page should show a different listing or detail page tomorrow it should only be a matter of replacing components.

Component folder#

The components folder can quickly become cluttered. It makes sense to group components in sub-folders based on their subject matter. So all components used on a certain list will be in src/components/certain-list.

Component reuse should be high so there will also be some kind of shared, utility or general purpose folder. Shared visual components related to material design (or another design system) should be organised in such a folder.

Component types#

Components come in a few flavours:

  • visual
  • composite
  • container

The most important idea of the components is to separate them by task and complexity.

CHECK: Changes in requirements and design should impact the minimum amount of components possible.

CHECK: Re-organising layout or page content should not impact components themselves

Visual components#

These are the most abundant. Visual components handle the display of data being provided to them in their properties. Ideally they should not be concerned with how the data was collected or prepared. Any action that might be triggered from a visual component should be an event emitted to a parent component or an application level state management solution.

CHECK: Unit testing visual components by supplying them different mock data should be trivial

Composite components#

A composite component is a combination of two or more other components with minimal code between them. The combination of 2 or more visual components that are always grouped together for example. So something like creating a more complete input component with label and input combined together.

TIP: Keep your components and what you're trying to do with them small for reuse purposes. Try to find a balance between having tiny components and multi-purpose ones.

Container components#

These are the components that handle data collection and preparation. They also combine multiple other components to create more complex task focused components. The previous example of the certain list component would be a container that prepares all the data required for its visual parts.

CHECK: Containers should only use and parameterise other components providing the logic for the interaction between them

React hooks and containers#

With the advent of React hooks we should need less container components that trickle down their data. If a visual component is simple enough it could display data directly from a hook negating the requirement for it to have a container component wrapping it.

A container will be focused on a task so it might create a localised context hook for its child components. The container will create the types that all its composite and visual components can rely on. Advantage of this is that if the container changes its types the compiler will help you track down the changes.

NOTE: The react hooks and state management playing field is rapidly changing. The principles discussed here should still apply but the implementation might take a different form.

Component type example#

If you apply the above you could end up with the following:

  • DiscountPage (Page)
  • DiscountView (Container)
  • DiscountList (Composite)
  • DiscountListItem (Visual)

Depending on complexity the DiscountList could become a container over time and the DiscountListItem a composite.