Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion src/React.res
Original file line number Diff line number Diff line change
Expand Up @@ -472,4 +472,4 @@ useEffectEvent is a React Hook that lets you extract non-reactive logic from you
[Read more on the React Documentation](https://react.dev/reference/react/useEffectEvent)
*/
@module("react")
external useEffectEvent: ('event => unit) => 'event => unit = "useEffectEvent"
external useEffectEvent: 'callback => 'callback = "useEffectEvent"
12 changes: 7 additions & 5 deletions src/ReactDOM.res
Original file line number Diff line number Diff line change
Expand Up @@ -91,22 +91,24 @@ module Ref = {

// Hooks

type formStatus<'state> = {
type formStatusAction = FormData.t => unit

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve async form action return values

When the parent form uses an async action, including the React.formAction<FormData.t> supported on line 107, useFormStatus().action refers to a function returning promise<unit> at runtime. Typing every status action as FormData.t => unit prevents callers from awaiting or handling that promise and can turn a rejected action into an unhandled rejection; this type should represent both synchronous and asynchronous form actions rather than discarding the return value.

Useful? React with 👍 / 👎.


type formStatus = {
/** If true, this means the parent <form> is pending submission. Otherwise, false. */
pending: bool,
/** An object implementing the FormData interface that contains the data the parent <form> is submitting. If there is no active submission or no parent <form>, it will be null. */
data: FormData.t,
data: nullable<FormData.t>,
/** This represents whether the parent <form> is submitting with either a GET or POST HTTP method. By default, a <form> will use the GET method and can be specified by the method property. */
method: [#get | #post],
method: nullable<[#get | #post]>,
/** A reference to the function passed to the action prop on the parent <form>. If there is no parent <form>, the property is null. If there is a URI value provided to the action prop, or no action prop specified, status.action will be null. */
action: React.action<'state, FormData.t>,
action: nullable<formStatusAction>,
}

external formAction: React.formAction<FormData.t> => string = "%identity"

/** `useFormStatus` is a Hook that gives you status information of the last form submission. */
@module("react-dom")
external useFormStatus: unit => formStatus<'state> = "useFormStatus"
external useFormStatus: unit => formStatus = "useFormStatus"

// Resource Preloading APIs

Expand Down
16 changes: 14 additions & 2 deletions src/ReactDOMServer.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ type resumeOptions<'error> = {
onError?: 'error => unit,
}

type resumeToPipeableStreamOptions<'error> = {
...resumeOptions<'error>,
onAllReady?: unit => unit,
onShellReady?: unit => unit,
onShellError?: 'error => unit,
}

type pipeableStream = {
pipe: ReactDOMStatic.nodeStream => ReactDOMStatic.nodeStream,
abort: unit => unit,
}

/**
resume streams a pre-rendered React tree to a Readable Web Stream.
[Read more on the React Documentation](https://react.dev/reference/react-dom/server/resume)
Expand All @@ -29,5 +41,5 @@ resumeToPipeableStream streams a pre-rendered React tree to a pipeable Node.js
external resumeToPipeableStream: (
React.element,
ReactDOMStatic.postponedState,
~options: resumeOptions<'error>=?,
) => promise<ReactDOMStatic.nodeStream> = "resumeToPipeableStream"
~options: resumeToPipeableStreamOptions<'error>=?,
) => pipeableStream = "resumeToPipeableStream"
Loading