2017-12-28 12 views
0

Ich habe Probleme bei der Integration von react-System-Benachrichtigungsmodul in meiner App, nachdem ich die Dokumentation über Reason React Ref gelesen habe Ich bin mir nicht sicher, warum die Referenz nicht den Stapel weitergegeben wird; Ein Hinweis würde sehr geschätzt werden.Wie definiert man die Komponente/Bindung, wenn React ref in Reasonml verwendet wird?

Ich bekomme den Fehler unten, ich habe diese Komponente in der Vergangenheit in React verwendet, aber es scheint, dass es ein Problem bei der Verwendung in ReasonML/React gibt. Ich vermute, dass eine Nullreferenz übergeben wird, die die Komponente bricht.

Elementtyp ist ungültig: ein String erwartet (für eingebaute Komponenten) oder eine Klasse/Funktion (für Composite-Bauteile) bekam aber: undefined. Sie haben wahrscheinlich vergessen, Ihre Komponente aus der Datei zu exportieren, in der sie definiert ist, , oder Sie haben standardmäßige und benannte Importe verwechselt.

Überprüfen Sie die Rendermethode Notifications.

Bindung:

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

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

Komponente

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> 
    ) 
}; 

Antwort

0

Nach einigen weiteren Untersuchungen, dank glensl Hinweis und einige Nachrichten ausgetauscht auf Discord posten ich die vollständige Antwort.

Die Frage wurde auf Art und Weise bsb Zusammenhang erzeugt die "require" Anweisung in der JavaScript-Ausgabe:

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

wurde emittiert als:

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

statt

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

Mightseem ein wenig hacky aber ich habe bsb, um das korrekte Javascript auszusenden war die folgende Aussage:

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

Dann mit einigen kleineren Optimierungen an die Wrapper-Komponente, konnte ich es mit dem folgenden Code zum Laufen bringen:

Modul ReactNotificationSystem = { [@ bs.module] externer reactClass: ReasonReact.reactClass = "react-notification-system/dist/NotificationSystem";

1

Meine Vermutung wäre, dass react-notification-system nicht als es6 Komponente verteilt ist, und daher nicht default nicht exportieren. Versuchen Sie default von der externen Entfernung:

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

Sie immer durch Ausprobieren die einfachste Implementierung zuerst beginnen sollte, dann bauen schrittweise von dort, um mögliche Fehlerursachen zu minimieren. Vor allem, wenn es sich um etwas handelt, das so fehleranfällig ist wie die js-Grenze. In diesem Fall wäre das ohne die komplexe ref-Behandlung. Sie werden wahrscheinlich feststellen, dass es immer noch nicht funktioniert, aufgrund der oben genannten, und dass Sie an der falschen Stelle gesucht haben, weil Sie mehr abgebissen haben, als Sie kauen können.

+0

Dank für den Zeiger:

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> ) }; 

Eine vollständige Probe Arbeitsprojekt kann auf Github here werden! – user465374

Verwandte Themen