React Photo Album

repository·main·Indexed 21 days ago

https://github.com/igordanchenko/react-photo-album

A responsive photo gallery component for React 18+ supporting Rows, Columns, and Masonry layouts. It features high performance, SSR compatibility with defaultContainerWidth and skeleton props, and automatic responsive image handling via srcSet and sizes. The library provides individual layout components (RowsPhotoAlbum, ColumnsPhotoAlbum, MasonryPhotoAlbum) as well as an aggregate PhotoAlbum component for switching layouts.

Tokens
14.3K
Snippets
44
Records
59
Agent score
72%

What's inside react-photo-album

  1. Customize rendered elements with render functions

    main

    React Photo Album allows full UI customization by providing custom render functions via the render prop. Each function receives the default element's props as the first argument (typically including style and className). Some functions also receive a second argument representing the photo rendering context.

    Photo Rendering Context

    When the second argument is provided, it contains:

    • photo: The Photo object.
    • index: The index of the photo in the original photos array.
    • width: Rendered photo width in pixels.
    • height: Rendered photo height in pixels.

    Available Render Functions

    • container: Customizes the main album div. Must forward the ref attribute to the underlying element.
    • track: Customizes row/column containers.
    • wrapper: Customizes the image wrapper (used when photos are not clickable).
    • link: Customizes the link element (used when a photo has an href).
    • button: Customizes the button element (used when an onClick callback is provided).
    • image: Customizes the <img> element.
    • extras: Renders custom markup immediately after each image (useful for absolute positioned icons).
    • photo: A complete override that replaces wrapper, link, button, image, and extras. It only receives onClick in the first argument.
    // Example: Customizing the container (must forward ref)
    <RowsPhotoAlbum
      photos={photos}
      render={{
        container: ({ ref, ...rest }) => <div ref={ref} {...rest} />,
      }}
    />
    
    // Example: Adding custom icons via extras
    <RowsPhotoAlbum
      photos={photos}
      render={{
        extras: (_, { photo, index }) => (
          <FavoriteIcon photo={photo} index={index} />
        ),
      }}
    />
    
    // Example: Complete photo override
    <RowsPhotoAlbum
      photos={photos}
      render={{
        photo: ({ onClick }, { photo, width, height }) => (
          <CustomPhoto
            photo={photo}
            width={width}
            height={height}
            onClick={onClick}
          />
        ),
      }}
    />
  2. How the different layouts work

    main

    React Photo Album provides three distinct layout algorithms:

    • Rows Layout: Arranges photos into rows with similar heights. It uses a dynamic programming algorithm (inspired by Knuth and Plass) to find optimal row breaks, preventing issues like stretched images or uneven rows caused by panoramas.
    • Columns Layout: Arranges photos into a predefined number of columns (set via the columns prop). It uses dynamic programming to partition photos into balanced groups and adjusts column widths based on aspect ratios so all columns have equal height.
    • Masonry Layout: Places each photo into the shortest available column. This results in columns of equal width, though the bottom edge of the container may not be perfectly flush.
  3. Use responsive props with functions

    main

    Most layout props (like columns, spacing, targetRowHeight, etc.) can be passed as a function that receives the containerWidth. This allows you to define custom responsive behavior based on the actual width of the album container.

    <ColumnsPhotoAlbum
      photos={photos}
      columns={(containerWidth) => {
        if (containerWidth < 400) return 2;
        if (containerWidth < 800) return 3;
        return 4;
      }}
    />
  4. Optimize layout recalculations with breakpoints

    main

    By default, the album recalculates its layout on every container width change (e.g., during window resizing). To improve performance and prevent excessive recalculations, provide a breakpoints array. The layout will then only be recalculated once per breakpoint interval.

    Example breakpoints: [300, 600, 1200]

    <RowsPhotoAlbum photos={photos} breakpoints={[300, 600, 1200]} />
  5. Enable Server-Side Rendering (SSR)

    main

    To prevent empty markup during SSR and ensure the layout is visible before hydration, provide the defaultContainerWidth prop.

    Note: If the actual container width differs from defaultContainerWidth, a layout shift may occur after hydration. To mitigate this, you can provide a fallback UI using the skeleton prop to be rendered during SSR.

  6. Handle Server-Side Rendering (SSR) and Layout Shift

    main

    By default, React Photo Album produces empty markup during SSR because the container width is unknown, which can cause Content Layout Shift (CLS) upon hydration. You can use one of the following three strategies to mitigate this:

    1. Default Container Width: Specify defaultContainerWidth to render markup on the server. This is ideal for fixed-width containers (e.g., sidebars) but may cause layout shift if the client-side width differs.
    2. Skeleton: Provide a fallback UI via the skeleton prop. This reserves space on the page to prevent content jumping, though images won't start downloading until after hydration unless you manually add prefetch links.
    3. Visibility Hidden: Render the album with visibility: hidden on the server using componentsProps. This prevents layout flashes and allows the browser to start downloading images before hydration.
    // 1. Default Container Width
    <RowsPhotoAlbum photos={photos} defaultContainerWidth={800} />
    
    // 2. Skeleton
    <RowsPhotoAlbum
      photos={photos}
      skeleton={<div style={{ width: "100%", minHeight: 800 }} />}
    />
    
    // 3. Visibility Hidden
    <RowsPhotoAlbum
      photos={photos}
      defaultContainerWidth={800}
      componentsProps={(containerWidth) =>
        containerWidth === undefined
          ? { container: { style: { visibility: "hidden" } } }
          : {}
      }
    />
  7. Use examples for library development

    main

    If you are developing the library and want to test changes in real-time within an example project, follow these steps to link the local library to an example:

    1. Build the library: In the root of the repository, install dependencies and start the library build script.

      npm install
      npm run start
    2. Link to an example: Navigate to the desired example directory, install its dependencies, and use npm link to point to the local library source.

      cd <example>
      npm install
      npm link ../..
      npm run dev
    3. Cleanup: To revert the example to use the published version of the library instead of your local link, run:

      cd <example>
      npm unlink --no-save react-photo-album
      npm unlink -g react-photo-album
      npm install
    # Build the library
    npm install
    npm run start
    
    # Link to an example
    cd <example>
    npm install
    npm link ../..
    npm run dev
    
    # Cleanup
    cd <example>
    npm unlink --no-save react-photo-album
    npm unlink -g react-photo-album
    npm install
  8. Implement advanced features with React Photo Album examples

    main

    For complex use cases, refer to the following specialized examples:

    • Customization: Demonstrates how to use custom render functions and various photo album props to extend the default behavior.
    • Sortable Gallery: Shows how to build a sortable gallery using @dnd-kit.
    • Next.js Image: Demonstrates integration with the Next.js Image component for optimized image loading.
    • Lightbox: Shows how to integrate a lightbox experience using yet-another-react-lightbox.
  9. Run the React Photo Album examples

    main

    To run a specific example from the repository, navigate to the example directory, install its dependencies, and start the development server.

    cd <example>
    npm install
    npm run dev

    The development server will start on port 5173 (or the next available port if 5173 is occupied).

    cd <example>
    npm install
    npm run dev
  10. Use the ServerPhotoAlbum component in React Server Components

    main

    The ServerPhotoAlbum component is designed for use within React Server Components (RSC) environments, such as Next.js App Router. This allows you to render the photo album on the server, improving performance and SEO by reducing the amount of JavaScript sent to the client.

    To implement this, you should use the ServerPhotoAlbum component provided by the react-photo-album-server-component package.