在 Reasonml 中使用 React ref 时如何定义组件/绑定?
How to defined component /binding when using React ref in Reasonml?
我在我的应用程序中集成 react-system-notification 模块时遇到问题,阅读了有关 Reason React Ref 的文档后,我不确定为什么不将引用传递到堆栈中;一个提示将不胜感激。
我一直收到以下错误,我过去曾在 React 中使用过此组件,但在 ReasonML/React 中使用时似乎存在一些问题。我怀疑传递了一个空引用,这破坏了组件。
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined. You
likely forgot to export your component from the file it's defined in,
or you might have mixed up default and named imports.
Check the render method of 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>
)
};
我的猜测是 react-notification-system
没有作为 es6 组件分发,因此不会导出 default
。尝试从外部删除 default
:
[@bs.module "react-notification-system"] external reactClass : ReasonReact.reactClass = "";
您应该始终首先尝试最简单的实现,然后从那里逐步构建,以最大程度地减少可能的错误原因。尤其是在处理像js边界这样容易出错的东西的时候。在这种情况下,没有复杂的 ref 处理。由于上述原因,您可能会发现它仍然无法正常工作,并且您一直在寻找错误的地方,因为您咬得太多了。
经过进一步调查,感谢 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");
可能看起来有点老套,但是我让 bsb 发出正确的 javascript 使用以下语句:
[@bs.module ] external reactClass : ReasonReact.reactClass = "react-notification-system/dist/NotificationSystem";
然后通过对包装器组件进行一些小的调整,我能够使用以下代码让它工作:
模块 ReactNotificationSystem = {
[@bs.module]外部反应类: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:
上找到完整的示例工作项目
我在我的应用程序中集成 react-system-notification 模块时遇到问题,阅读了有关 Reason React Ref 的文档后,我不确定为什么不将引用传递到堆栈中;一个提示将不胜感激。
我一直收到以下错误,我过去曾在 React 中使用过此组件,但在 ReasonML/React 中使用时似乎存在一些问题。我怀疑传递了一个空引用,这破坏了组件。
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of
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>
)
};
我的猜测是 react-notification-system
没有作为 es6 组件分发,因此不会导出 default
。尝试从外部删除 default
:
[@bs.module "react-notification-system"] external reactClass : ReasonReact.reactClass = "";
您应该始终首先尝试最简单的实现,然后从那里逐步构建,以最大程度地减少可能的错误原因。尤其是在处理像js边界这样容易出错的东西的时候。在这种情况下,没有复杂的 ref 处理。由于上述原因,您可能会发现它仍然无法正常工作,并且您一直在寻找错误的地方,因为您咬得太多了。
经过进一步调查,感谢 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");
可能看起来有点老套,但是我让 bsb 发出正确的 javascript 使用以下语句:
[@bs.module ] external reactClass : ReasonReact.reactClass = "react-notification-system/dist/NotificationSystem";
然后通过对包装器组件进行一些小的调整,我能够使用以下代码让它工作:
模块 ReactNotificationSystem = { [@bs.module]外部反应类: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:
上找到完整的示例工作项目