I am very new to ReasonML. I am able to successfully create a stateless component with ReasonReact, but I have not figured out how I might add a custom method to the component (e.g. Next.js' static getInitialProps
).
When attempting to define the getInitialProps
method on the component, I receive a The field getInitialProps does not belong to type ReasonReact.componentSpec
error.
How should I add this define this custom method on the React component?
Component
let str = ReasonReact.stringToElement;
let component = ReasonReact.statelessComponent("Index");
let make = (~items: Listings.items, _children) => {
...component,
getInitialProps: () =>
Js.Promise.(
Endpoints.fetchListings()
|> then_(Fetch.Response.json)
|> then_((json) => Js.Json.decodeArray(json) |> resolve)
),
render: (_self) =>
<div>
(List.length(items) > 0 ? <Listings items /> : <Loading />)
</div>
};
let default =
ReasonReact.wrapReasonForJs(
~component,
(jsProps) => make(~items=jsProps##items, [||])
);
Error
We've found a bug for you!
/Users/davidcalhoun/Sites/web/evergreen-roots/pages/Index.re 7:3-17
5 │ let make = (~items: Listings.items, _children) => {
6 │ ...component,
7 │ getInitialProps: () =>
8 │ Js.Promise.(
9 │ Endpoints.fetchListings()
This record expression is expected to have type
ReasonReact.componentSpec ('a, 'b, 'c, 'd, 'e)
The field getInitialProps does not belong to type ReasonReact.componentSpec
Answered in Discord, reposting here:
You can't define arbitrary methods on the component like that. See that
...component
? That's spread a record with static fields and updating a few fields like you did, e.g.render
.Also, you can't directly pass a ReasonReact component into a next method, I believe. It's probably asking for a react component class. See the interop section on how to expose the underlying js class for the js side.
In the meantime you can probably just wrap that component in a thin layer of js component that defines the
getInitialProps
So you'd have a reactjs component that has
getInitialProps
, that renders a ReasonReact component that exposed the underlying class through interop. If I'm understanding you right, you'd also write ReasonReact bindings to that js wrapper if you're using that wrapper from Reason. Which makes this process a bit contrived, but you're hitting a pathological case here.As an side: ideally, the Next.js API would ask for a component class, and a
getInitialProps
on the side, a totally agnostic function that's not attached onto the component class. That'd greatly simplify the binding process on the Reason side.