1

我在我的应用程序中集成 react-system-notification 模块时遇到问题,阅读了有关Reason React Ref的文档我不确定为什么引用没有传递到堆栈中;一个提示将不胜感激。

我不断收到以下错误,我过去曾在 React 中使用过这个组件,但在 ReasonML/React 中使用时似乎存在一些问题。我怀疑传递了一个空引用,这会破坏组件。

元素类型无效:应为字符串(用于内置组件)或类/函数(用于复合组件)但得到:未定义。您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。

检查Notifications.

捆绑:

module NotificationSystem = {    
    [@bs.module "react-notification-system"] external reactClass : ReasonReact.reactClass = "default";

    let make = ( children ) => 
    ReasonReact.wrapJsForReason(
        ~reactClass, 
        ~props=Js.Obj.empty(),
        children
    )
};

零件

type action =
  | AddNotification(string);

type state = {
    _notificationSystem: ref(option(ReasonReact.reactRef)),
};

let setNotificationSystemRef = (notificationRef, {ReasonReact.state: state}) => 
  state._notificationSystem := Js.toOption(notificationRef) ;

let component = ReasonReact.reducerComponent("Notifications");

let addNotification = (message, state) => {   
    switch state._notificationSystem^ {
    | None => ()
    | Some(r) => ReasonReact.refToJsObj(r)##addNotification({"message": message, "level": "success"});      
    }
};

let make = (_children) => {
    ...component,
    initialState: () => {_notificationSystem: ref(None) },
    reducer: (action, state) =>
        switch action {
            | AddNotification(message) =>  ReasonReact.SideEffects(((_) => addNotification(message, state)))
        },
    render: ({handle, reduce}) => (
        <div>
            <NotificationSystem ref=(handle(setNotificationSystemRef)) />
            <button onClick=(reduce( (_) => AddNotification("Test Notification Test"))) > (ReasonReact.stringToElement("Click")) </button> 
        </div>
    )
};
4

2 回答 2

1

经过进一步调查,感谢glensl提示和在 Discord 上交换的一些消息,我发布了完整的答案。

该问题与 bsb 在 javascript 输出中生成“require”语句的方式有关:

[@bs.module "react-notification-system"] external reactClass : ReasonReact.reactClass = "default";

被发射为:

var ReactNotificationSystem = require("react-notification-system");

代替

var NotificationSystem = require("react-notification-system");

看起来有点 hacky 但是我让 bsb 发出正确的 javascript 使用以下语句:

[@bs.module ] external reactClass : ReasonReact.reactClass = "react-notification-system/dist/NotificationSystem";

然后对包装器组件进行一些小的调整,我能够使用以下代码使其工作:

模块 ReactNotificationSystem = { [@bs.module ] 外部 reactClass : ReasonReact.reactClass = "react-notification-system/dist/NotificationSystem";

let make = ( children ) => 
ReasonReact.wrapJsForReason(
    ~reactClass, 
    ~props=Js.Obj.empty(),
    children
)
};

type action =
  | AddNotification(string);

type state = {
    _notificationSystem: ref(option(ReasonReact.reactRef)),
};

let setNotificationSystemRef = (notificationRef, {ReasonReact.state}) => 
  state._notificationSystem := Js.Nullable.to_opt(notificationRef) ;

let component = ReasonReact.reducerComponent("Notifications");

let addNotification = (message, state) => {   
    switch state._notificationSystem^ {
    | None => ()
    | Some(r) => ReasonReact.refToJsObj(r)##addNotification({"message": message, "level": "success"});      
    }
};

let make = (_children) => {
    ...component,
    initialState: () => {_notificationSystem: ref(None) },
    reducer: (action, state) =>
        switch action {
            | AddNotification(message) =>  ReasonReact.SideEffects(((_) => addNotification(message, state)))
        },
    render: ({handle, reduce}) => (
    <div>             
        <ReactNotificationSystem ref=(handle(setNotificationSystemRef)) />
        <button onClick=(reduce( (_) => AddNotification("Hello"))) > (ReasonReact.stringToElement("Click")) </button> 
    </div>
  )
};

可以在 Github 上找到完整的示例工作项目

于 2017-12-29T07:53:13.237 回答
1

我的猜测是它react-notification-system不会作为 es6 组件分发,因此不会 export default。尝试default从外部删除:

[@bs.module "react-notification-system"] external reactClass : ReasonReact.reactClass = "";

您应该始终首先尝试最简单的实现,然后从那里逐步构建,以尽量减少可能的错误原因。尤其是在处理像 js 边界这样容易出错的东西时。在这种情况下,将没有复杂的 ref 处理。由于上述原因,您可能会发现它仍然无法正常工作,并且您一直在寻找错误的地方,因为您咬得比咀嚼多。

于 2017-12-28T12:21:51.470 回答