Skip to content

Commit

Permalink
Restrict useFormState in Server Components (vercel#55417)
Browse files Browse the repository at this point in the history
I based my changes on vercel#49331, which did this for useFormStatus.

While I was editing the file, I noticed that useOptimistic was incorrectly categorized as a `react-dom` package export, but it's actually exported from `react`. So I fixed that, too.

Co-authored-by: Zack Tanner <1939140+ztanner@users.noreply.github.com>
  • Loading branch information
acdlite and ztanner committed Sep 16, 2023
1 parent 676e3ae commit 0bfd480
Show file tree
Hide file tree
Showing 10 changed files with 27 additions and 22 deletions.
3 changes: 2 additions & 1 deletion packages/next-swc/crates/core/src/react_server_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ pub fn server_components<C: Comments>(
JsWord::from("flushSync"),
JsWord::from("unstable_batchedUpdates"),
JsWord::from("experimental_useFormStatus"),
JsWord::from("experimental_useOptimistic"),
JsWord::from("experimental_useFormState"),
],
invalid_server_react_apis: vec![
JsWord::from("Component"),
Expand All @@ -609,6 +609,7 @@ pub fn server_components<C: Comments>(
JsWord::from("useState"),
JsWord::from("useSyncExternalStore"),
JsWord::from("useTransition"),
JsWord::from("experimental_useOptimistic"),
],
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
useSyncExternalStore,
} from 'react'

import { experimental_useOptimistic as useOptimistic } from 'react'

export default function () {
return null
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState } from 'react';
import { createContext } from 'react';
import { useEffect, useImperativeHandle } from 'react';
import { Component, createFactory, PureComponent, useDeferredValue, useInsertionEffect, useLayoutEffect, useReducer, useRef, useSyncExternalStore } from 'react';
import { experimental_useOptimistic as useOptimistic } from 'react';
export default function() {
return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,10 @@
: ^^^^^^^^^^^^^^^^^^^^
17 | } from 'react'
`----

x NEXT_RSC_ERR_REACT_API: experimental_useOptimistic
,-[input.js:18:1]
18 |
19 | import { experimental_useOptimistic as useOptimistic } from 'react'
: ^^^^^^^^^^^^^^^^^^^^^^^^^^
`----
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom'

import {
experimental_useOptimistic as useOptimistic,
experimental_useFormStatus,
experimental_useFormState,
} from 'react-dom'

export default function () {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom';
import { experimental_useOptimistic as useOptimistic, experimental_useFormStatus } from 'react-dom';
import { experimental_useFormStatus, experimental_useFormState } from 'react-dom';
export default function() {
return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@
: ^^^^^^^^^^^^^^^^^^^^^^^
`----

x NEXT_RSC_ERR_REACT_API: experimental_useOptimistic
x NEXT_RSC_ERR_REACT_API: experimental_useFormStatus
,-[input.js:3:1]
3 | import {
4 | experimental_useOptimistic as useOptimistic,
4 | experimental_useFormStatus,
: ^^^^^^^^^^^^^^^^^^^^^^^^^^
5 | experimental_useFormStatus,
5 | experimental_useFormState,
`----

x NEXT_RSC_ERR_REACT_API: experimental_useFormStatus
x NEXT_RSC_ERR_REACT_API: experimental_useFormState
,-[input.js:4:1]
4 | experimental_useOptimistic as useOptimistic,
5 | experimental_useFormStatus,
: ^^^^^^^^^^^^^^^^^^^^^^^^^^
4 | experimental_useFormStatus,
5 | experimental_useFormState,
: ^^^^^^^^^^^^^^^^^^^^^^^^^
6 | } from 'react-dom'
`----
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom'

import {
experimental_useOptimistic as useOptimistic,
experimental_useFormStatus,
experimental_useFormState,
} from 'react-dom'

export default function () {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom';
import { experimental_useOptimistic as useOptimistic, experimental_useFormStatus } from 'react-dom';
import { experimental_useFormStatus, experimental_useFormState } from 'react-dom';

export default function() {
return null;
}
13 changes: 3 additions & 10 deletions test/development/acceptance-app/server-components.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,19 +258,12 @@ describe('Error Overlay for server components', () => {
)

await check(async () => {
expect(
await browser
.waitForElementByCss('#nextjs__container_errors_desc')
.text()
).toContain(
'experimental_useOptimistic only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/react-client-hook-in-server-component'
)
const html = await browser.eval('document.documentElement.innerHTML')
expect(html).toContain('experimental_useOptimistic')
return 'success'
}, 'success')

expect(next.cliOutput).toContain(
'experimental_useOptimistic only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/react-client-hook-in-server-component'
)
expect(next.cliOutput).toContain('experimental_useOptimistic')

await cleanup()
})
Expand Down

0 comments on commit 0bfd480

Please sign in to comment.