After I finished bootcamp, I wanted to keep learning by rebuilding my final project - a picture-sharing app for me and my friends. It's very special to me because before I really knew much about coding, I told them I was going to build it for them. Some years ago we had a brilliant holiday to Florida, we went to Disney, did all that fun stuff and came back with a tonne of photos but never got together to share all those happy memories. Here's how it works right now:
At first I had this grand plan to rewrite it in a whole different stack, teaching myself all these different technologies. I got a bit muddled trying all that at once, so for now the back end can stay as it is - it already works well and I have the endpoints in place so I'll start by concentrating on the front. I only had 2 weeks to build the app at bootcamp, so although it works, the code could be better. This is the first part of what I imagine will be an occasional series of blogs about what I learn as I work through the rebuild.
So like I said, I built a working project in 2 weeks but I wanted to write parts of it differently. The front end is scaffolded with create-react-app and all the components are conditionally rendered using ternaries, with outcomes based mostly on different bits of state. Setting and updating all those bits of state got complicated after a while, and I thought I could go back afterwards and refactor the code to use React Router - easy, right? Well you can, and I tried, but it wasn't straightforward. Routing became my first priority for the rebuild.
The app is going to have a header with buttons going to login and signup pages, so I know I want routes for those. I also need a route for the homepage. My app uses JWT for authorisation so if there is a token present in localStorage I want an albums route to display the photo albums for the logged-in user. If there is no token, this route shouldn't work so the user needs to be shown the login form.
I created a new react app and used the quick start code from the react training website to get going. It's a really nice way to get used to links and routes by just playing about. There's a bit on nested routes which will come in handy when I get to displaying the contents of a particular album.
Once the basics were laid out with some simple components just containing h1's stating their purpose, I needed to work out how to implement the albums page: the original version of my app uses a function which checks for a token in localStorage, called at the time the album page component mounts. If there is a token, it means a user is currently logged-in, so it fetches all of that user's albums from the database.
I didn't know how to represent this with routes until I found an excellent blog on this platform by Sophie, a former grad of and teacher at the Flatiron School. After following along with first part I was able to implement this solution into my App component:
Above, there are the regular routes that I have so far, with an additional authenticated (protected) route pointing to the component that displays a page with all of a user's albums.
The authenticated route looks a bit confusing but in essence is just a functional component.
It takes in props including the AlbumsPage component, and returns a Route component. The composition of the Route is determined by its render method, which checks for the presence of a token in localStorage: if there is one, it means an authenticated user is logged-in, so go ahead and call the AlbumsPage component that was passed in. If not, use the Redirect component. Redirect is a feature of react-router-dom, you can read more about it here. Essentially it enables you to dictate what route you want the user redirected to, instead of the URL that was requested. Helpfully, you can remember the location you were redirected from.
I don't need to grab all the content from the back end yet, I just want to check whether I implemented the authenticated route correctly, so I tested it in the browser by using the console to set and clear a token...
It all works, thanks @sophiedebenedetto ! This is really nice and neat because rather than having those different functions in different files, I have so far kept all my routing in one place where I can see it clearly. Just what I wanted.
Next I'll go put some handlers on the login form and hook it up to the back end so I can log in one of the actual users from the database...