Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions docs/api/remix.md
Original file line number Diff line number Diff line change
Expand Up @@ -1555,14 +1555,13 @@ These are fully featured utilities for handling fairly simple use cases. It's no
**Example:**

```tsx
const uploadHandler = unstable_createFileUploadHandler({
maxFileSize: 5_000_000,
file: ({ filename }) => filename,
});

export const action: ActionFunction = async ({
request,
}) => {
const uploadHandler = unstable_createFileUploadHandler({
maxFileSize: 5_000_000,
file: ({ filename }) => filename,
});
const formData = await unstable_parseMultipartFormData(
request,
uploadHandler
Expand Down Expand Up @@ -1594,13 +1593,12 @@ The `filter` function accepts an `object` and returns a `boolean` (or a promise
**Example:**

```tsx
const uploadHandler = unstable_createMemoryUploadHandler({
maxFileSize: 500_000,
});

export const action: ActionFunction = async ({
request,
}) => {
const uploadHandler = unstable_createMemoryUploadHandler({
maxFileSize: 500_000,
});
const formData = await unstable_parseMultipartFormData(
request,
uploadHandler
Expand Down Expand Up @@ -1709,12 +1707,12 @@ Your job is to do whatever you need with the `stream` and return a value that's

We have the built-in `unstable_createFileUploadHandler` and `unstable_createMemoryUploadHandler` and we also expect more upload handler utilities to be developed in the future. If you have a form that needs to use different upload handlers, you can compose them together with a custom handler, here's a theoretical example:

```tsx
```tsx filename=file-upload-handler.server.tsx
import type { UploadHandler } from "@remix-run/{runtime}";
import { unstable_createFileUploadHandler } from "@remix-run/{runtime}";
import { createCloudinaryUploadHandler } from "some-handy-remix-util";

export const fileUploadHandler =
export const standardFileUploadHandler =
unstable_createFileUploadHandler({
directory: "public/calendar-events",
});
Expand All @@ -1724,9 +1722,9 @@ export const cloudinaryUploadHandler =
folder: "/my-site/avatars",
});

export const multHandler: UploadHandler = (args) => {
export const fileUploadHandler: UploadHandler = (args) => {
if (args.name === "calendarEvent") {
return fileUploadHandler(args);
return standardFileUploadHandler(args);
} else if (args.name === "eventBanner") {
return cloudinaryUploadHandler(args);
} else {
Expand Down
25 changes: 25 additions & 0 deletions docs/pages/gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,31 @@ export default function SomeRoute() {

Even better, send a PR to the project to add `"sideEffects": false` to their package.json so that bundlers that tree shake know they can safely remove the code from browser bundles.

Similarly, you may run into the same error if you call a function at the top-level scope of your route module that depends on server-only code.

For example, [Remix upload handlers like `unstable_createFileUploadHandler` and `unstable_createMemoryUploadHandler`](../api/remix#uploadhandler) use Node globals under the hood and should only be called on the server. You can call either of these functions in a `*.server.js` or `*.server.ts` file, or you can move them into your route's `action` or `loader` function:

```tsx filename=app/routes/some-route.jsx
import { unstable_createFileUploadHandler } from "@remix-run/{runtime}";

// Instead of this…
const uploadHandler = unstable_createFileUploadHandler({
maxFileSize: 5_000_000,
file: ({ filename }) => filename,
});

// …do this

export async function action({ request }) {
const uploadHandler = unstable_createFileUploadHandler({
maxFileSize: 5_000_000,
file: ({ filename }) => filename,
});

// ...
}
```

> Why does this happen?

Remix uses "tree shaking" to remove server code from browser bundles. Anything inside of Route module `loader`, `action`, and `headers` exports will be removed. It's a great approach but suffers from ecosystem compatibility.
Expand Down