Create, Read and Delete UI
Integrate Reagent and Reframe to create UI for listing and deleting graphics.
Create, read and delete UI#
With the functionality in place, we will now build the user interface for creating, reading, and deleting graphics. Here's the wireframe we started with:
Title and create button#
The page title "Graphics" and the Create button can be clubbed into a component called
header component renders a
:div for the title and a Blueprint
The call-to-action button dispatches the
:a.d.f/create-graphic action, similar to what we did using the REPL. The component also subscribes to
:a.d.f/creating-graphic? and uses the subscription value as
:loading prop to the
Button component. We have not written this subscription yet.
For this code to work, we need to
require the necessary libraries:
We can pull the
::creating-graphic? flag from
app-db using a subscription in
a.d.firebase namespace. We defined this flag when we wrote the handler for
If you find the usage of the key repetitive, you can use the reframe-utils library. It provides a wrapper to Reframe API and allows for concise event handlers, effects, and subscriptions. With
reframe-utils, the above subscription can be written as:
We can add this component to
page component so it renders on
If everything worked well, you'll see the header component on the
/graphics route. Clicking the
Create New button will create a new graphic (and print to console):
The job of this component is to fetch all the graphics from Firebase and display them as a grid. The graphics can be fetched by dispatching the
:a.d.f/fetch-graphics event, but this is a side-effect!
The data should be fetched automatically when the component mounts. In modern React, this is achieved using the
useEffect hook. In traditional React, the
component-did-mount method is used to define the effects that need to be triggered when a component mounts.
To use the
useEffect hook, we need to
reactify Reagent components, ie convert them to React components. This means losing access to ratoms. Since Reframe's
app-db is just a Reagent atom under the hood, hooks don't play well with Reframe either.
It's a common approach in the Clojure frontend community to let the router handle mount interactions. This requires the developer to use a more bare-bones routing engine so the tweaks can be made.
But since we are using React Router, we'll use Reagent's
create-class method to create a class-based component. We'll then define a
component-did-mount method, and dispatch the
::fetch-graphics event in that method:
Unlike a functional Reagent component, a class-based Reagent component is defined by passing a map to
reagent.core/create-class method. This map accepts various key value pairs like:
:component-did-mount (fn )- equivalent to React's
:display-name- name of the component for debugging and logging purposes
:reagent-render- equivalent to React's
A full list of accepted key-value pairs can be found in the official docs.
We want our
graphics-list component to show a loading indicator when graphics are being fetched, then render each graphic. Let's create the subscription that pulls the required data from
This will provide us with a map: