我在我的应用程序中集成react-system-notification模块时遇到了问题,阅读了有关Reason React Ref的文档我不知道为什么引用没有传递到堆栈中;一个提示将非常感激。
我一直收到下面的错误,我过去在React中使用过这个组件,但似乎在ReasonML / React中使用时存在一些问题。我怀疑传递了一个空引用,这会破坏组件。
元素类型无效:需要一个字符串(用于内置组件) 或类/函数(对于复合组件)但得到:undefined。您 可能忘记从您定义的文件中导出组件, 或者您可能混淆了默认导入和命名导入。
检查
的渲染方法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>
)
};
答案 0 :(得分:1)
我的猜测是react-notification-system
不会作为es6组件分发,因此不会导出default
。尝试从外部删除default
:
[@bs.module "react-notification-system"] external reactClass : ReasonReact.reactClass = "";
您应该首先尝试最简单的实现,然后从那里逐步构建,以尽量减少可能的错误原因。特别是在处理像js边界一样容易出错的事情时。在这种情况下,没有复杂的ref处理。你可能会发现它仍然不起作用,因为上述情况,并且你一直在寻找错误的地方因为你咬得比你能咀嚼的多。
答案 1 :(得分: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");
Mightseem有点hacky然而我得到bsb发出正确的javascript使用以下声明:
[@bs.module ] external reactClass : ReasonReact.reactClass = "react-notification-system/dist/NotificationSystem";
然后对包装器组件稍作调整,我能够使用以下代码:
模块ReactNotificationSystem = { [@ bs.module] external 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上找到完整的示例工作项目here: