Как определить компонент / привязку при использовании React ref в Reasonml?
У меня проблемы с интеграцией модуля реакции-системы-уведомлений в моем приложении, прочитав документацию по 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>
)
};
2 ответа
После дальнейшего расследования, благодаря подсказке glennsl и обмену сообщениями на Discord, я выкладываю полный ответ.
Проблема была связана со способом, которым bsb генерировал оператор "require" в выводе javascript:
[@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";
Затем, внеся небольшие изменения в компонент оболочки, я смог заставить его работать со следующим кодом:
module ReactNotificationSystem = {[@ bs.module] external responseClass: ReasonReact.reactClass = "реагировать-система уведомлений /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 здесь:
Я думаю, что react-notification-system
не распространяется как компонент es6 и поэтому не экспортируется default
, Попробуйте удалить default
из внешнего:
[@bs.module "react-notification-system"] external reactClass : ReasonReact.reactClass = "";
Вы должны всегда начинать с того, чтобы сначала опробовать простейшую реализацию, а затем постепенно наращивать ее, чтобы минимизировать возможные причины ошибок. Особенно, когда имеешь дело с чем-то таким же подверженным ошибкам, как граница js. В этом случае это было бы без сложной обработки ссылок. Вы, вероятно, обнаружите, что это все еще не работает из-за вышеизложенного, и что вы искали не в том месте, потому что откусили больше, чем могли прожевать.