Skip to content

Conversation

@pedrobslisboa
Copy link
Collaborator

@pedrobslisboa pedrobslisboa commented Oct 5, 2025

Related #227

While working on the router, I verified that nextjs pushes some of the model information to the streaming.
Some of those value that we may want is the dynamic params
The routing for example the initial payload is:

export type InitialRSCPayload = { /** buildId */ b: string /** assetPrefix */ p: string /** initialCanonicalUrlParts */ c: string[] /** couldBeIntercepted */ i: boolean /** initialFlightData */ f: FlightDataPath[] /** missingSlots */ m: Set<string> | undefined /** GlobalError */ G: [React.ComponentType<any>, React.ReactNode | undefined] /** postponed */ s: boolean /** prerendered */ S: boolean } /** Sample result: 0: {  "b": "development",  "f": [  [  "children",  "note",  "children",  [  "id",  "1757357171759",  "d"  ],  "children",  "__PAGE__",  [  "__PAGE__",  {}  ],  [  "__PAGE__",  [  "$",  "$1",  "c",  {  "children": [  "$L2",  [  [  "$",  "script",  "script-0",  {  "src": "/_next/static/chunks/node_modules_81a97b._.js",  "async": true,  "nonce": "$undefined"  },  null  ],  [  "$",  "script",  "script-1",  {  "src": "/_next/static/chunks/_e6d2ac._.js",  "async": true,  "nonce": "$undefined"  },  null  ],  [  "$",  "script",  "script-2",  {  "src": "/_next/static/chunks/app_note_%5Bid%5D_page_tsx_60d685._.js",  "async": true,  "nonce": "$undefined"  },  null  ]  ],  [  "$",  "$L4",  null,  {  "children": "$L5"  },  null  ]  ]  },  null  ],  {},  null  ],  [  "$",  "$1",  "h",  {  "children": [  "$7",  "$11"  ]  },  null  ]  ]  ],  "S": false } */

I propose to change the client_value to a clearer context, like Model.t and apply it to the model_value type, which can have several values, like List, Assoc, Json, Promise, Element.

module Model = struct type 'element t = | Function : 'server_function Runtime.server_function -> 'element t | List : 'element t list -> 'element t | Assoc : (string * 'element t) list -> 'element t | Json : Yojson.Basic.t -> 'element t | Error : error -> 'element t | Element : 'element -> 'element t | Promise : 'a Js.Promise.t * ('a -> Yojson.Basic.t) -> 'element t end type element = | Lower_case_element of lower_case_element | Upper_case_component of string * (unit -> element) | Async_component of string * (unit -> element Lwt.t) | Client_component of { props : client_props; client : unit -> element; import_module : string; import_name : string } | List of element list | Array of element array | Text of string | DangerouslyInnerHtml of string | Fragment of element | Empty | Provider of element | Consumer of element | Suspense of { key : string option; children : element; fallback : element } and lower_case_element = { key : string option; tag : string; attributes : JSX.prop list; children : element list } and client_props = (string * model_value) list and model_value = element React.Model.t

We also need to change the render_model to receive the React.model_value instead of React.element:

val render_model : ?env:[ `Dev | `Prod ] -> ?debug:bool -> ?subscribe:(string -> unit Lwt.t) -> React.Model.t -> unit Lwt.t 

Q: Why not use Json for list and assoc?

A: Cause those can be composed by others model_values, while Json is only for Yojson

React.Model.Assoc( ["bar", React.Assoc(["element", React.Element(<div> {React.String("I'm a nested element :3")} </div> )])] ["foo", React.List([React.Element(<div> {React.String("Hey")} </div>, React.Json(`String("Yah!")))])] ["baz", React.Promise(React.Element(<div> {React.String("Who is Lola?")} </div>))] )

Q: Why scope client_value in Model.t

A: We cannot have | List : client_value list -> client_value as it will conflict with the element type React.List. An alternative is to prefix it with Model_ (Model_list) or Client_ (Client_list), but it's meh.

Error: Unbound type constructor React.client_value File "packages/react/src/React.ml", line 398, characters 2-44: 398 | | List : client_value list -> client_value ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error (warning 30 [duplicate-definitions]): the constructor List is defined in both types element and client_value.

Question

Is it missing any type?

@pedrobslisboa pedrobslisboa self-assigned this Oct 7, 2025
@pedrobslisboa pedrobslisboa added the enhancement New feature or request label Oct 7, 2025
* origin/main: chore: add context to turn_element_into_payload revert: client_value to push revert: Fiber abstraction of render_element revert: remove push on async component revert: remove debug info changes chore: add better naming to root_data_payload feat: change serialize for to_chunk Improve CI (#313) feat: improve debugging due to new fiber/model contextg Add environtmnet for srr Client component's can't be functions refact: improve the Fiber and Model stream context fix: align Suspense with reason-react (#311)
@pedrobslisboa pedrobslisboa force-pushed the feat/model-values branch 2 times, most recently from fabfa98 to 417d6b3 Compare October 27, 2025 10:54
@pedrobslisboa pedrobslisboa force-pushed the feat/model-values branch 2 times, most recently from e0d6aad to 0b6a8bd Compare October 27, 2025 12:42
@pedrobslisboa
Copy link
Collaborator Author

As @davesnx is out, I'm following the merge, and we can discuss any questions later.

@pedrobslisboa pedrobslisboa merged commit cc50f18 into main Oct 27, 2025
5 checks passed
@pedrobslisboa pedrobslisboa deleted the feat/model-values branch October 27, 2025 13:15
pedrobslisboa added a commit that referenced this pull request Oct 27, 2025
* origin/main: Specify model values at React (#309)
pedrobslisboa added a commit that referenced this pull request Oct 27, 2025
* origin/main: Specify model values at React (#309) feat: allow async in client props (#315) chore: add context to turn_element_into_payload revert: client_value to push revert: Fiber abstraction of render_element revert: remove push on async component revert: remove debug info changes chore: add better naming to root_data_payload feat: change serialize for to_chunk Improve CI (#313) feat: improve debugging due to new fiber/model contextg Add environtmnet for srr Client component's can't be functions refact: improve the Fiber and Model stream context fix: align Suspense with reason-react (#311) fix: adjust doc link on tests Fix broken link to browser_ppx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

2 participants