Skip to content
Closed
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
5 changes: 5 additions & 0 deletions .changeset/media-react-hook-form-v8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"sanity-plugin-media": patch
---

Update react-hook-form to v8 (8.0.0-beta.3), which has first-class React Compiler support, and re-enable React Compiler for the asset details form. Dialog footers (and the confirm dialog header) are no longer declared as inline components, so they no longer remount whenever form state changes.
13 changes: 13 additions & 0 deletions plugins/sanity-plugin-media/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ or
yarn add sanity-plugin-media
```

### Peer dependency warnings

The plugin uses [`react-hook-form`](https://react-hook-form.com/) v8 together with [`@hookform/resolvers`](https://www.npmjs.com/package/@hookform/resolvers), which doesn't declare react-hook-form v8 in its peer dependencies yet (it declares `react-hook-form ^7.55.0`), even though the resolver contract is unchanged and works fine with v8. Until a v8-compatible release is published, tell your package manager to allow it:

- `npm`: install with the `--legacy-peer-deps` flag
- `pnpm`: set [`peerDependencyRules.allowedVersions`](https://pnpm.io/settings#peerdependencyrulesallowedversions) in `pnpm-workspace.yaml`:

```yaml
peerDependencyRules:
allowedVersions:
'@hookform/resolvers>react-hook-form': '8.0.0-beta.3'
```

## Usage

Add it as a plugin in your `sanity.config.ts` (or .js) file:
Expand Down
2 changes: 1 addition & 1 deletion plugins/sanity-plugin-media/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"pluralize": "^8.0.0",
"react-dropzone": "^11.7.1",
"react-file-icon": "^1.6.0",
"react-hook-form": "catalog:",
"react-hook-form": "catalog:react-hook-form-v8",
"react-redux": "^9.3.0",
"react-select": "^5.10.2",
"react-virtuoso": "^4.18.11",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@ export default function Details({
creditLine,
locales,
}: DetailsProps) {
'use no memo'
// React Compiler memoizes the register() field JSX using asset-derived deps only.
// That can leave Save stuck disabled while the DOM still updates (uncontrolled inputs).
// Tags work because they use Controller; string fields use register and need this opt-out.

const hasLocales = locales && locales.length > 0
const [activeLocaleTab, setActiveLocaleTab] = useState(0)
const folderId = currentAsset?.opt?.media?.folder?._ref
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const DialogConfirm = (props: Props) => {
handleClose()
}

const Footer = () => (
const footer = (
<Box padding={3}>
<Flex justify="space-between">
<Button fontSize={1} mode="bleed" onClick={handleClose} text="Cancel" />
Expand All @@ -51,7 +51,7 @@ const DialogConfirm = (props: Props) => {
</Box>
)

const Header = () => (
const header = (
<Flex align="center">
<Box paddingX={1}>
<WarningOutlineIcon />
Expand All @@ -61,16 +61,7 @@ const DialogConfirm = (props: Props) => {
)

return (
<Dialog
animate
// oxlint-disable-next-line react/react-compiler
footer={<Footer />}
// oxlint-disable-next-line react/react-compiler
header={<Header />}
id="confirm"
onClose={handleClose}
width={1}
>
<Dialog animate footer={footer} header={header} id="confirm" onClose={handleClose} width={1}>
<Box paddingX={4} paddingY={4}>
<Stack space={3}>
{dialog?.title && <Text size={1}>{dialog.title}</Text>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const DialogFolderCreate = (props: Props) => {
}
}, [creatingError, setError])

const Footer = () => (
const footer = (
<Box padding={3}>
<Flex justify="flex-end">
<FormSubmitButton
Expand All @@ -76,15 +76,7 @@ const DialogFolderCreate = (props: Props) => {
)

return (
<Dialog
animate
// oxlint-disable-next-line react/react-compiler
footer={<Footer />}
header="Create Folder"
id={id}
onClose={handleClose}
width={1}
>
<Dialog animate footer={footer} header="Create Folder" id={id} onClose={handleClose} width={1}>
<Box as="form" padding={4} onSubmit={handleSubmit(onSubmit)}>
<button style={{display: 'none'}} tabIndex={-1} type="submit" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const DialogTagCreate = (props: Props) => {
}
}, [creatingError, setError])

const Footer = () => (
const footer = (
<Box padding={3}>
<Flex justify="flex-end">
{/* Submit button */}
Expand All @@ -79,15 +79,7 @@ const DialogTagCreate = (props: Props) => {
)

return (
<Dialog
animate
// oxlint-disable-next-line react/react-compiler
footer={<Footer />}
header="Create Tag"
id={id}
onClose={handleClose}
width={1}
>
<Dialog animate footer={footer} header="Create Tag" id={id} onClose={handleClose} width={1}>
{/* Form fields */}
<Box as="form" padding={4} onSubmit={handleSubmit(onSubmit)}>
{/* Hidden button to enable enter key submissions */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const DialogTagEdit = (props: Props) => {
}
}, [client, handleTagUpdate, tagItem?.tag])

const Footer = () => (
const footer = (
<Box padding={3}>
<Flex justify="space-between">
{/* Delete button */}
Expand Down Expand Up @@ -162,15 +162,7 @@ const DialogTagEdit = (props: Props) => {
}

return (
<Dialog
animate
// oxlint-disable-next-line react/react-compiler
footer={<Footer />}
header="Edit Tag"
id={id}
onClose={handleClose}
width={1}
>
<Dialog animate footer={footer} header="Edit Tag" id={id} onClose={handleClose} width={1}>
{/* Form fields */}
<Box as="form" padding={4} onSubmit={handleSubmit(onSubmit)}>
{/* Deleted notification */}
Expand Down
25 changes: 22 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ catalogs:
react-dom: ^19.2
sanity: ^5 || ^6.0.0-0
styled-components: ^6.1
# react-hook-form v8 beta (first-class React Compiler support), currently only
# used by sanity-plugin-media; the default catalog stays on v7 for other plugins.
react-hook-form-v8:
react-hook-form: 8.0.0-beta.3

# When running `pnpm add`, reuse a dependency's catalog version automatically if
# it already exists in a catalog, so shared deps stay aligned on a single version.
Expand Down Expand Up @@ -173,6 +177,10 @@ peerDependencyRules:
# @bynder/compact-view does not declare react 19 in its peers yet, but works fine with it
'@bynder/compact-view>react': '19'
'@bynder/compact-view>react-dom': '19'
# @hookform/resolvers has no react-hook-form v8 compatible release yet (peers ^7.0.0);
# the resolver contract is unchanged and it works with the v8 beta (documented in
# the sanity-plugin-media README)
'@hookform/resolvers>react-hook-form': '8.0.0-beta.3'
Comment on lines +180 to +183

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this change to make sense we have to document the peer dep warning in the plugin README.md, similar to what bynder does regarding react 19 peer deps

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, given this will land into a warning in user land I think we should skip it until react-hook-form v8 is out of beta, which will probably land with the fix for the peer dep.

The fix is already in place, this was only to re enable the compiler, but this is not a hot path , this is in the edit dialog.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is not beta of @hookform/resolvers


publicHoistPattern:
# Allows setting vite/client in dev/test-studio/tsconfig.json without installing vite
Expand Down
Loading