homeaboutvideotry it nowpricingdocs
Guide

How to add image upload to a React app

A working uploader, a file ID to store, and a resized preview, without writing an upload endpoint.

What an upload feature actually needs

Letting a user pick an image looks like one <input type="file">. The rest is the part that takes the time: somewhere to put the bytes, a way to get them there from the browser, a limit on what is accepted, and a URL you can show the image from afterwards.

The usual DIY route is an API endpoint that accepts a multipart request, a bucket to store the result, and some code to hand back a URL. That is a fair amount of surface area for a profile picture. A hosted upload service replaces all of it with a component and a key, and that is the route this guide takes.

1. Install the React package

npm install @cd2/fileboy-react

You also need a public key. Create a free app and copy the key from its Keys page. To try the code first without an account, use the shared key demo. Anything uploaded with it is visible to everyone, so swap in your own key before real use.

2. Wrap your app in the provider

The provider holds your public key. The public key is safe to ship in browser code: it can only do what your app's permission settings allow.

App.tsx
import { FileboyProvider } from "@cd2/fileboy-react"

export function App() {
  return (
    <FileboyProvider publicKey="YOUR_PUBLIC_KEY">
      <ProfileForm />
    </FileboyProvider>
  )
}

3. Drop in the uploader

FileUploader renders a drop zone with a button, shows progress, and calls onFileUploaded when the file has landed. allow works like the accept attribute on a normal file input, so image/* rejects anything that is not an image before it leaves the browser.

ProfileForm.tsx
import { useState } from "react"
import { FileUploader } from "@cd2/fileboy-react"

export function ProfileForm() {
  const [avatarId, setAvatarId] = useState<string>()

  return (
    <FileUploader
      allow="image/*"
      onFileUploaded={file => setAvatarId(file.id)}
    />
  )
}

The callback receives the file's data: id, name, mime, fileSize, hash and createdAt, plus any metadata you attached. Save the `id`. That one string is all your database needs.

4. Show the image

Image takes the ID and builds the URL for you. Because images are resized by URL, you can ask for exactly the size you are displaying instead of shipping the full upload.

ProfileForm.tsx
import { useState } from "react"
import { FileboyProvider, FileUploader, Image } from "@cd2/fileboy-react"

function ProfileForm() {
  const [avatarId, setAvatarId] = useState<string>()

  return (
    <div>
      <FileUploader
        allow="image/*"
        onFileUploaded={file => setAvatarId(file.id)}
      />

      {avatarId && (
        <Image
          id={avatarId}
          transforms={[{ type: "resize", width: 160, height: 160, fit: "cover" }]}
        />
      )}
    </div>
  )
}

export function App() {
  return (
    <FileboyProvider publicKey="YOUR_PUBLIC_KEY">
      <ProfileForm />
    </FileboyProvider>
  )
}

Store the file ID, not the URL. The URL changes with the size and format you ask for. The ID does not, so one stored value can serve a thumbnail today and a full-width banner next month.

Things to decide before you ship

  • Who may upload. The public key is meant to be in browser code, so anyone who has it can upload to your app. Limit file types with allow for your users' benefit, and keep an eye on usage in the dashboard.
  • More than one file. Swap FileUploader for MultiFileUploader and use onFilesUploaded, which receives an array.
  • Not using React. The same uploader is available as a script tag. See the JavaScript library docs.
  • Existing files. Pass defaultFileId to show a previously uploaded file in the uploader when editing a record.

Checked against the current libraries in November 2026. Found something that no longer works? Tell us.

Go deeper

Still choosing a tool?

Fileboy is small on purpose. This comparison says where it fits and where another option is the better call.

Fileboy vs Uploadcare · All comparisons

Try it

The free plan needs no card and includes 1,000 files, so you can run every example above.

More guides: Resize images on the fly with a URL · Stream video with HLS without running ffmpeg · Add captions and subtitles to a video · Embed a video on any website · All guides

Add Fileboy to your next project

We built Fileboy to stop rebuilding file handling for every app. Create an app, paste your key and upload a file. The free plan needs no card.