首页 > 解决方案 > 从 aws-amplify 绑定到高阶组件

问题描述

什么是 bucklescript 寻找满足Functions are not valid as a React child.以下示例产生的错误。

我有这个绑定到withAuthenticatorfrom aws-amplify-react

[@bs.deriving abstract]
type props = {
  [@bs.as "Comp"]
  comp: React.element,
  [@bs.optional] includeGreetings: bool,
};

[@genType.import ("aws-amplify-react", "withAuthenticator")] [@react.component]
external make:(
    ~props:props,
  ) => React.element = "withAuthenticator";
let default = make;

Demo.re我使用绑定如下:

let props = {
  WithAuthenticator.props(
    ~comp={
      <App />;
    },
    ~includeGreetings=true,
    (),
  );
};
Js.log(props);
[@react.component]
let app = () => <WithAuthenticator props />;

然后在App.jsDemo.re这样使用:

import Amplify from 'aws-amplify';
import {app as App } from './Demo.bs';
import awsconfig from './aws-exports';
import './App.css';
Amplify.configure(awsconfig);

export default App;

这会产生以下错误:

 Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
    in withAuthenticator (created by Demo$app)
    in Demo$app (at src/index.js:7)

我想了解这意味着什么,以便在它再次出现时进行处理。

这就是编译好的 bucklescript 代码所在的位置Demo.bs.js

// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE
'use strict';

var React = require("react");
var App$ReactHooksTemplate = require("./App.bs.js");
var WithAuthenticator$ReactHooksTemplate = require("../aws/WithAuthenticator.bs.js");

var props = {
  Comp: React.createElement(App$ReactHooksTemplate.make, { }),
  includeGreetings: true
};

console.log(props);

function Demo$app(Props) {
  return React.createElement(WithAuthenticator$ReactHooksTemplate.make, {
              props: props
            });
}

var app = Demo$app;

exports.props = props;
exports.app = app;
/* props Not a pure module */

可以在此处找到此问题的重现。

更新:

在这里,我试图在下面跟进@glennsl 的评论/答案。

// define a type modeling what `withAuthenticator` is expecting
[@bs.deriving abstract]
type props = {
  [@bs.as "Comp"]
  comp: React.element,
  [@bs.optional]
  includeGreetings: bool,
};
// use bs.module instead of gentype
[@bs.module ("aws-amplify-react", "withAuthenticator")]
external withAuthenticator: props => React.component(props) =
  "withAuthenticator";
module AppWithAuthenticator = {
  [@bs.obj]
  external makeProps:
    (~children: 'children, unit) => {. "children": 'children} =
    "";
  let make = props => withAuthenticator(props);
};

这就是它的使用方式,但不能编译。


module AppWithAuth = {
  let props = {
    props(
      ~comp={
        <App />;
      },
      ~includeGreetings=true,
      (),
    );
  };
  [@react.component]
  let make = () => {
    <AppWithAuthenticator props />;
  };
};

编译错误:

>>>> Start compiling
[1/3] Building src/aws/AuthenticatorBS-ReactHooksTemplate.cmj

  We've found a bug for you!
  /Users/prisc_000/working/DEMOS/my-app/src/aws/AuthenticatorBS.re 34:6-25

  32 │   [@react.component]
  33 │   let make = () => {
  34 │     <AppWithAuthenticator props />;
  35 │   };
  36 │ };

  This call is missing an argument of type props

标签: interopaws-amplifyhigher-order-componentsreasonreason-react

解决方案


这些方面的东西应该起作用:

[@genType.import ("aws-amplify-react", "withAuthenticator")]
external withAuthenticator : (React.component('a), bool) => React.component('a) = "withAuthenticator";

module AppWithAuthenticator = {
  [@bs.obj]
  external makeProps: (~children: 'children=?, unit) => {. "children": 'children } = "";
  let make = withAuthenticator(App.make, true);
};

ReactDOMRe.renderToElementWithId(<AppWithAuthenticator />, "root");

external withAuthenticator : ...将外部 HOC 构造函数声明为一个函数,该函数接受一个 react 组件和一个 bool,并返回一个组件,该组件将接受完全相同的 props,因为'a这两个位置都使用了类型变量。

module AppWithAuthenticator ...将 HOC 构造函数应用于App组件并对其进行设置,以便它可以与 JSX 一起使用。这和直接导入一个react组件基本一样,只是我们通过函数调用的方式获取外部组件,而不是直接导入。

最后,最后一行只是演示了如何使用它。

请注意,我显然没有正确测试这一点,因为我没有设置项目aws-amplify等。我也从未使用过genType,但对于这个用例来说似乎很简单。


推荐阅读