【问题标题】:How to add custom method to ReasonReact component?如何将自定义方法添加到 ReasonReact 组件?
【发布时间】:2017-11-27 00:55:12
【问题描述】:

我对 ReasonML 很陌生。我能够使用 ReasonReact 成功创建无状态组件,但我还没有弄清楚如何向组件添加自定义方法(例如 Next.js' static getInitialProps)。

尝试在组件上定义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

【问题讨论】:

    标签: reactjs nextjs reason reason-react


    【解决方案1】:

    在 Discord 中回答,在此转发:

    你不能像那样在组件上定义任意方法。看到...component了吗?这是使用静态字段传播记录并像您一样更新一些字段,例如render.

    另外,我相信你不能直接将 ReasonReact 组件传递给 next 方法。它可能要求一个反应组件类。 js端如何暴露底层js类见interop section

    与此同时,您可能只需将该组件包装在定义 getInitialProps 的 js 组件的薄层中

    因此,您将拥有一个具有 getInitialProps 的 reactjs 组件,该组件呈现一个通过互操作公开底层类的 ReasonReact 组件。 如果我对您的理解正确,那么如果您使用的是来自 Reason 的包装器,那么您还会将 ReasonReact 绑定写入该 js 包装器。这使得这个过程有点做作,但你在这里遇到了一个病态的案例。

    作为一个方面:理想情况下,Next.js API 会要求一个组件类,以及一个 getInitialProps 在旁边,一个完全不可知的函数,它不附加到组件类上。这将大大简化 Reason 端的绑定过程。

    【讨论】:

      【解决方案2】:

      我想在我的原因反应 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 中的内容传递给 &lt;Component someParam=manualStuff {...pageProps} /&gt;,这可以作为参数进入您的原因反应页面。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-22
        • 1970-01-01
        • 2021-11-11
        • 1970-01-01
        • 1970-01-01
        • 2012-08-06
        • 2014-08-04
        相关资源
        最近更新 更多