Building a basic photo album in React

joedietrichdev

Joe Dietrich

Posted on October 20, 2021

Building a basic photo album in React

Purpose

I've loved taking pictures since I was little, but I don't really have a place to show off the best pictures I've taken. I decided to build myself a little photo gallery using React for the frontend, and a very simple JSON Server based backend.

Basic Features

For my photo gallery, I broke the required features down to the basics:

  • Display images in a gallery format
  • Display an individual image
  • Add an image to the gallery
  • Edit the image's description
  • Delete the image if needed

To those, I added a couple additional features:

  • Mark images a "favorites"
  • Display favorite images in a second gallery

What I Used

To get to my basic feature set, I decided to use:

Building the App

The photo gallery has four major components, which each have their own Routes:

  • Gallery, which displays image thumbnails in a grid and links to individual ImageDetails: "/images" or "/favorites"
  • ImageDetails, which displays a larger version of a selected image, along with the image description: nested under the gallery paths - "/images/" or "/favorites/"
  • ImageDetailsEdit, which provides a way to edit the description of an image: nested under the image detail paths - "/images//edit" or "/favorites//edit"
  • NewImage, which contains a form and the functions needed to add new images to the gallery: "/new"

Within and surrounding these components, I created a number of additional components to style the contents of each page and provide additional functionality. The majority of the components I created this way were Styled Components.

Challenges

This was the first time I'd used Styled Components in a meaningful way. In the past, I've used a single stylesheet and classes to apply styles, but I wanted to challenge myself to something new.

My first thought when reading the documentation was to wonder about the use of sting literals I hadn't encountered much before. If you haven't seen a styled component component before, it looks something like this:

import styled from "styled-components";

const DetailCard = styled.div`
  display: grid;
  grid: "p i n" auto ". d ." auto / min-content 1fr min-content;
  max-width: 800px;
  margin: 0 auto;
`;
Enter fullscreen mode Exit fullscreen mode

Breaking this down:

styled is the default export from the styled-components module.

div is a function property of the styled object.

A function? But where are the parentheses?

Notice that the CSS styles themselves are contained within the backticks (\) of an ES6 template literal. In this case, it is a tagged template literal. The tag of a tagged template literal is a function (here, div) that takes an array of strings as its first argument, and the values of any substitutions (indicated by the ${} syntax in a template literal) as additional arguments.

This means the example above could be rewritten as the below, with no change in functionality:

const DetailCard = styled.div([
  `
  display: grid;
  grid: "p i n" auto ". d ." auto / min-content 1fr min-content;
  max-width: 800px;
  margin: 0 auto;
`,
]);
Enter fullscreen mode Exit fullscreen mode

Things get a bit more complicated when you introduce those substitutions. For example, with styled components, you can use props to change a component's styles:

const NavButton = styled.button`
  grid-area: ${(props) => props.area};
  padding: 0 1rem;
`;
Enter fullscreen mode Exit fullscreen mode

This allows us to pass in an area prop to define where the component will display:

<NavButton area="n">Next</NavButton>
Enter fullscreen mode Exit fullscreen mode

And translates to CSS like this:

  grid-area: n;
  padding: 0 1rem;
Enter fullscreen mode Exit fullscreen mode

This would be equivalent to, but much less convenient than, calling the button function property of styled directly:

const NavButton = styled.button(
  ['grid-area: ','; padding: 0 1rem;'],
  (props) => props.area);
Enter fullscreen mode Exit fullscreen mode

Once I was able to wrap my head around what this syntax meant, it was much easier to use styled components.

Styled Component Tips:

  • Don't be afraid of making a lot of styled components, as long as they each serve a purpose!
  • Keep single-use components near where you use them. I kept mine in the same file as the component I used them in.
  • If you find yourself using the same (or similar) styles or components in multiple places, you can pull the styled component into its own file and reuse it! Don't repeat yourself if you don't have to!
  • Read the documentation
  • Read this (Josh W Comeau Article on Styled Components in React)[https://www.joshwcomeau.com/css/styled-components/]. I found it very helpful, especially the section on making sure you have a single source of styles for each component.

Plans for the future

As I have time, I'm planning to implement:

  • Basic login and user validation
  • Real photo upload instead of url submissions
  • Additional albums
  • Server-side photo resizing

Visit the most recent version of the site

You can see a working version of the site at: https://photo-album.joedietrich.dev

💖 💪 🙅 🚩
joedietrichdev
Joe Dietrich

Posted on October 20, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related