# Integrating Bee-JS with React Applications for Swarm Decentralized Storage

> Integrate Bee-JS with React for Swarm decentralized storage. Upload, download, and manage files seamlessly using the official JavaScript SDK with modern React patterns.

- Repository: [Ethersphere/awesome-swarm](https://github.com/ethersphere/awesome-swarm)
- Tags: tutorial
- Published: 2026-03-01

---

**Bee-JS provides the official JavaScript SDK for React developers to upload, download, and manage files on the Swarm decentralized storage network through a promise-based API that integrates seamlessly with modern React patterns.**

The ethersphere/awesome-swarm repository identifies Bee-JS as the primary JavaScript SDK for interacting with Swarm's Bee nodes via REST API. By integrating Bee-JS into a React application, you can build declarative UI components that handle decentralized file storage directly from the browser while maintaining reactive state management and upload progress tracking.

## Architecture Overview

A typical Bee-JS React integration follows a layered architecture that separates presentation logic from storage operations.

| Component | Role | Interaction |
|-----------|------|-------------|
| **React UI** | Renders forms, buttons, progress indicators, and content viewers. | Invokes Bee-JS methods through custom hooks and event handlers. |
| **Bee-JS Client** (`@ethersphere/bee-js`) | Wraps the Bee HTTP API, handling authentication, request signing, and response parsing. | Exposes methods including `uploadFile`, `downloadFile`, `uploadDirectory`, `getFeed`, and `setFeed`. |
| **Bee Node** | The Swarm storage backend that persists chunks, manifests, and feeds. | Receives HTTP calls from Bee-JS and returns Swarm hashes (e.g., `bzz://<hash>`). |
| **State Management** | Tracks upload progress, Swarm references, and error states. | Updated by React hooks that wrap asynchronous Bee-JS operations. |

The upload flow works as follows: a user selects a file in a React component, a custom hook calls `bee.uploadFile()`, Bee-JS streams the data to the Bee node's `/files` endpoint, and the hook updates React state with the returned Swarm hash to trigger a UI re-render.

## Setting Up Bee-JS in Your React Project

### Installation

Install the official SDK package via npm:

```bash
npm install @ethersphere/bee-js

```

### Client Initialization

Create a centralized client instance to avoid duplicate initialization and share configuration across components. In [`src/beeClient.ts`](https://github.com/ethersphere/awesome-swarm/blob/main/src/beeClient.ts), instantiate the `Bee` class with your node endpoint:

```typescript
import { Bee } from '@ethersphere/bee-js';

export const bee = new Bee('http://localhost:1633', {
  // Optional: specify API token if your node requires authentication
  // apiKey: process.env.REACT_APP_BEE_API_KEY,
});

```

This client wraps the Bee HTTP API and exposes methods for file operations, feed management, and postage batch handling.

## Uploading Files to Swarm with React Hooks

### Creating the useBeeUpload Hook

Encapsulate upload logic in a reusable hook to keep components declarative. In [`src/hooks/useBeeUpload.ts`](https://github.com/ethersphere/awesome-swarm/blob/main/src/hooks/useBeeUpload.ts), wrap `bee.uploadFile` with progress tracking:

```typescript
import { useState, useCallback } from 'react';
import { bee } from '../beeClient';

export function useBeeUpload() {
  const [hash, setHash] = useState<string | null>(null);
  const [progress, setProgress] = useState<number>(0);
  const [error, setError] = useState<string | null>(null);

  const upload = useCallback(
    async (file: File) => {
      try {
        setError(null);
        setProgress(0);
        const response = await bee.uploadFile(file, {
          onUploadProgress: (event) => {
            const percent = Math.round((event.loaded * 100) / event.total);
            setProgress(percent);
          },
        });
        setHash(response.reference); // Swarm hash, e.g., `bzz://...`
      } catch (e: any) {
        setError(e.message);
      }
    },
    [],
  );

  return { hash, progress, error, upload };
}

```

The `onUploadProgress` callback enables real-time progress updates by calculating the percentage from the event's `loaded` and `total` properties.

### Building the UploadForm Component

Create a presentational component in [`src/components/UploadForm.tsx`](https://github.com/ethersphere/awesome-swarm/blob/main/src/components/UploadForm.tsx) that consumes the hook:

```tsx
import React, { ChangeEvent } from 'react';
import { useBeeUpload } from '../hooks/useBeeUpload';

export function UploadForm() {
  const { hash, progress, error, upload } = useBeeUpload();

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) upload(file);
  };

  return (
    <div>
      <input type="file" onChange={handleChange} />
      {progress > 0 && <p>Uploading… {progress}%</p>}
      {hash && (
        <p>
          Uploaded! Swarm address:{' '}
          <a href={`https://bzz.link/${hash}`} target="_blank" rel="noopener noreferrer">
            {hash}
          </a>
        </p>
      )}
      {error && <p style={{ color: 'red' }}>Error: {error}</p>}
    </div>
  );
}

```

This component handles file selection, delegates the upload to the hook, and conditionally renders progress indicators or the final Swarm reference.

## Downloading and Displaying Swarm Content

### The useBeeDownload Hook

For retrieving content, create [`src/hooks/useBeeDownload.ts`](https://github.com/ethersphere/awesome-swarm/blob/main/src/hooks/useBeeDownload.ts) to wrap `bee.downloadFile`:

```typescript
import { useState, useCallback } from 'react';
import { bee } from '../beeClient';

export function useBeeDownload() {
  const [dataUrl, setDataUrl] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const download = useCallback(async (hash: string) => {
    try {
      setError(null);
      const file = await bee.downloadFile(hash);
      const blob = new Blob([file.fileData], { type: file.contentType });
      setDataUrl(URL.createObjectURL(blob));
    } catch (e: any) {
      setError(e.message);
    }
  }, []);

  return { dataUrl, error, download };
}

```

The hook converts the downloaded `fileData` into a Blob URL suitable for rendering in browser elements like images or download links.

### Rendering Downloaded Images

In [`src/components/ImageViewer.tsx`](https://github.com/ethersphere/awesome-swarm/blob/main/src/components/ImageViewer.tsx), use the hook to fetch and display Swarm-hosted images:

```tsx
import React, { useEffect } from 'react';
import { useBeeDownload } from '../hooks/useBeeDownload';

export function ImageViewer({ hash }: { hash: string }) {
  const { dataUrl, error, download } = useBeeDownload();

  useEffect(() => {
    download(hash);
  }, [hash, download]);

  if (error) return <p style={{ color: 'red' }}>{error}</p>;
  if (!dataUrl) return <p>Loading…</p>;

  return <img src={dataUrl} alt="Swarm content" style={{ maxWidth: '100%' }} />;
}

```

This pattern separates data fetching from presentation, allowing the component to handle loading and error states declaratively.

## Summary

Integrating Bee-JS with React applications for Swarm decentralized storage requires three core layers:

- **Centralized Client Configuration**: Initialize the `Bee` class once in [`src/beeClient.ts`](https://github.com/ethersphere/awesome-swarm/blob/main/src/beeClient.ts) to manage API endpoints and authentication tokens.
- **Custom Hooks for Async Operations**: Wrap `uploadFile` and `downloadFile` in hooks like `useBeeUpload` and `useBeeDownload` to handle progress tracking, error states, and Blob conversion.
- **Declarative UI Components**: Build presentational components that consume these hooks, rendering file inputs, progress bars, and content viewers based on the Swarm hashes returned by the Bee node.

This architecture aligns with React's component-driven model while leveraging Bee-JS's promise-based API to interact with the Swarm network as documented in the ethersphere/awesome-swarm repository.

## Frequently Asked Questions

### How does Bee-JS handle authentication with Bee nodes?

Bee-JS supports API key authentication through the `apiKey` configuration option passed to the `Bee` constructor. If your node requires a gateway token for restricted endpoints, include it in the client initialization in [`src/beeClient.ts`](https://github.com/ethersphere/awesome-swarm/blob/main/src/beeClient.ts) to ensure all requests include the proper authentication headers.

### Can I track upload progress when storing files on Swarm?

Yes. The `uploadFile` method accepts an `onUploadProgress` callback that receives progress events containing `loaded` and `total` byte counts. By calculating the percentage in your React hook and updating state, you can drive progress indicators in your UI components as demonstrated in the `useBeeUpload` implementation.

### What Swarm hash format does Bee-JS return after uploading?

Bee-JS returns a Swarm reference (hash) in the `response.reference` property, which represents the content-addressed identifier for your stored data. You can use this hash to construct gateway URLs like `https://bzz.link/${hash}` for browser access or pass it to `downloadFile` for retrieval within your application.

### Is Bee-JS compatible with React Server Components or Next.js App Router?

Bee-JS is designed for browser and Node.js environments, but its file handling methods expect browser APIs like `File` and `Blob` for uploads. For React Server Components, invoke Bee-JS methods in Client Components (using the `"use client"` directive) or in API routes where you can handle multipart form data and stream responses appropriately.