如何将自定义方法添加到ReasonReact组件?

我对ReasonML非常陌生。我能够使用ReasonReact成功创建一个无状态组件,但是我还没有弄清楚如何向该组件添加自定义方法(例如Next.js的staticgetInitialProps)。

尝试getInitialProps在组件上定义方法时,出现The field getInitialProps does not belong to type ReasonReact.componentSpec错误。

我应该如何在React组件上添加此定义此自定义方法的方法?

零件

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, [||])
  );

错误

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
宝儿神奇2020/03/23 15:51:23

我想在我的理性Next.js页面中获取上下文,并找到了解决方案。这是访问上下文以检测我们是否正在服务器上渲染并将布尔值传递给您的ReasonReact组件的示例:

let make = (~onServer, _children) => {
/* component code goes here */ 
};

let default =
  ReasonReact.wrapReasonForJs(~component, jsProps => make(~onServer=jsProps##onServer, [||]));

let getInitialProps = context =>
  Js.Promise.make((~resolve, ~reject as _) => {
    let onServer =
      switch (Js.Nullable.toOption(context##req)) {
      | None => false
      | Some(_) => true
      };
    resolve(. {"onServer": onServer});
  });

let inject = [%bs.raw {| (cls, fn) => cls.getInitialProps = fn |}];

inject(default, getInitialProps);

https://github.com/zeit/next.js/issues/4202#issuecomment-439175214 所有信贷@tmepple和@ -rase谁张贴的解决方案有!

另一种解决方案是将“ _app.js”保留为纯js,然后从该getInitialProps中传递内容,这些<Component someParam=manualStuff {...pageProps} />内容可以作为参数输入到您的原因反应页面中。

神奇达蒙2020/03/23 15:51:23

在Discord中回答,在此重新发布:

您不能像这样在组件上定义任意方法。看到了...component吗?这样可以分散具有静态字段的记录,并像您一样更新一些字段,例如render

而且,我相信您不能直接将ReasonReact组件传递给下一个方法。它可能要求一个React组件类。有关如何在js端公开底层js类的信息,请参见互操作性部分

在此期间,您可能只需将该组件包装在js组件的薄层中即可, getInitialProps

因此,您将拥有一个具有的reactjs组件getInitialProps,该组件呈现一个ReasonInteract组件,该组件通过互操作公开了基础类。如果我理解正确的话,如果您使用的是来自Reason的包装,那么您也应该将ReasonReact绑定写入该js包装。这使这个过程有些虚构,但是您在这里遇到了一个病态的案例。

一方面:理想情况下,Next.js API将要求一个组件类,而getInitialProps在侧面,则是一个完全不可知的功能,该功能未附加到组件类上。这样可以大大简化“原因”方面的绑定过程。