We have authenticated our users, but now they're stuck on the login screen. This chapter is about building re-usable containers to redirect users to authorized pages.
Our app has a
/graphics route, that lists all the graphics a user has created. This will be our root private route - ie a user will be redirected here as soon as she logs in.
For common components like navigation, auth containers, rich text editors and so on, we'll use the
app.components.* namespace. This means we'll have three top-level namespaces:
app.domain.*for domain-specific functionality
app.pages.*for top-level routes and
app.components.*for shared components
We'd like to point out again that this is only one way you could do it - feel free to experiment with different structuring for your apps.
Let's define a
app.components.auth/public that will wrap
/register route components.
The job of this component is to listen to
:a.d.f/me and redirect the user to
/graphics route as soon as she logs in. If the user is not logged in, it renders the children (ie the login form):
public component subscribed to
:a.d.f/me defined in the last chapter redirects to
/graphics if a user is logged in.
The argument to the
children, should not be confused with
props.children. This is a Reagent component. The
children in this case means the vector of
divs that make up the login page.
& children to allow for multiple Hiccup forms like:
If we used
children in place of
& children, Reagent would only render the last form and ignore all others, ie it would only render
[:div "form 2"] in the example above.
:<> is the shorthand for React Fragment. In React, a component can return only one form. Since we allow the children to be a list of forms, we wrap it in a Fragment so React doesn't complain.
Redirect component from React Router is used to perform the Redirect using a component.
If we wrap the
:a.p.login component with
auth/public after we
:require it, we will get redirected to
/graphics on successful login:
Notice how all components are now wrapped under
auth/public. The above example is truncated, you will have more lines of code in your component.
We created a test user while setting up Firebase. Try to log in with the test credentials and you'll be redirected to
After logging in, if you try to visit
/login by manually altering the URL, the app will redirect you to
Top navigation and logout UI#
It's standard to have a top global nav with some details about the user and associated actions, such as settings, profile, and logout.
Since our users can now log in, let's make them feel at home by showing their email and a logout option. We'll use Blueprint's
Navbar has support to align items to the left or right, add headings, dividers, and much more. We recommend checking the component props if you'd like to learn more.
We will create a
Navbar wrapper and call it
Nav will be used throughout the application - ie it belongs to
app.components.nav namespace. We are going to define
app.components.nav/top component for the top navigation. In an application with multiple nav bars, multiple components can be defined in this namespace:
we subscribe to the logged-in user
bg-pink-200sets the nav background to a shade of pink (you can try other colors)
(.-Group Navbar)is equal to
:alignprop helps align the group to either left or right
we render a
Navbar.Headingin the left group
we render two buttons in the right group
the logout button dispatches
:a.d.f/logoutevent (which we haven't created yet)