2017-11-15 13 views
1

Ich versuche Reason-React. Ich stehe vor einem Problem, wenn ich versuche, einer Komponente einen Schlüssel hinzuzufügen.Unbound Datensatz Feld ID Fehler

Ich habe eine TodoApp, die eine Liste von TodoItem als Status nimmt. Die App funktioniert einwandfrei, wenn ich keinen Schlüssel für das TodoItem habe. Wenn ich es hinzufüge, erhalte ich jedoch einen Kompilierungsfehler. Ich füge die Dateien hier als Referenz:

TodoItem.re:

type item = { 
    id: int, 
    title: string, 
    completed: bool 
}; 

let lastId = ref(0); 

let newItem =() => { 
    lastId := lastId^ + 1; 
    {id: lastId^, title: "Click a button", completed: false} 
}; 

let toString = ReasonReact.stringToElement; 

let component = ReasonReact.statelessComponent("TodoItem"); 

let make = (~item, children) => { 
    ...component, 
    render: (self) => 
    <div className="item"> 
     <input _type="checkbox" checked=(Js.Boolean.to_js_boolean(item.completed)) /> 
     (toString(item.title)) 
    </div> 
}; 

TodoApp.re:

let toString = ReasonReact.stringToElement; 

type state = {items: list(TodoItem.item)}; 

type action = 
    | AddItem; 

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

let currentItems = [TodoItem.{id: 0, title: "ToDo", completed: false}]; 

let make = (children) => { 
    ...component, 
    initialState:() => {items: currentItems}, 
    reducer: (action, {items}) => 
    switch action { 
    | AddItem => ReasonReact.Update({items: [TodoItem.newItem(), ...items]}) 
    }, 
    render: ({state: {items}, reduce}) => { 
    let numOfItems = List.length(items); 
    <div className="app"> 
     <div className="title"> 
     (toString("What to do")) 
     <button onClick=(reduce((_evt) => AddItem))> (toString("Add Something")) </button> 
     </div> 
     <div className="items"> 
     (
      ReasonReact.arrayToElement(
      Array.of_list(
       (List.map((item) => <TodoItem key=(string_of_int(item.id)) item />, items)) 
       /*List.map((item) => <TodoItem item />, items) This works but the above line of code with the key does not*/ 
      ) 
     ) 
     ) 
     </div> 
     <div className="footer"> (toString(string_of_int(numOfItems) ++ " items")) </div> 
    </div> 
    } 
}; 

Ich habe einen Kommentar in der Nähe der Linie hinzugefügt haben, wo der Fehler auftritt. Der Fehler lautet Unbound record field id, aber ich bin nicht in der Lage, herauszufinden, wie es nicht gebunden ist. Was fehlt mir hier?

Antwort

2

Typ-Inferenz ist leider ein wenig begrenzt, wenn es darum geht, den Typ eines Datensatzes aus einem anderen Modul basierend auf der Verwendung von Datensatzfeldern abzuleiten, also müssen Sie ihm etwas helfen. Zwei Optionen, die funktionieren sollen, sind:

mit Anmerkungen versehen, die Art von ìtem:

List.map((item: TodoItem.item) => <TodoItem key=(string_of_int(item.id)) item />) 

oder lokal um das Modul zu öffnen, wo das Datensatzfeld verwendet wird:

List.map((item) => <TodoItem key=(string_of_int(item.TodoItem.id)) item />) 
+1

Es ist nicht wirklich ein Typinferenz Problem, aber ein Scoping-Problem (wie der ungebundene Wertfehler zu sagen scheint). Record-Dateien sind, wie andere benannte Werte, durch den Namen ihres definierenden Moduls qualifiziert und sollten daher mit der Syntax: Module.name aufgerufen werden. Die Open-Direktive erlaubt es, den Modulnamen und den Punkt wegzulassen, indem der aktuelle Bereich um die benannten Werte eines Moduls erweitert wird. Hier nehme ich an, dass das explizite Annotieren des Elementtyps den Bereich lokal erweitert, um den TodoItem.item-Typ hinzuzufügen. – ghilesZ

+0

@ghilesZ Das macht irgendwie Sinn, aber ich finde es seltsam (oder zumindest ungewöhnlich), dass der Bereich dann auf einen bestimmten Typ beschränkt wäre. – glennsl

+0

Es hat funktioniert, aber ich verstehe nicht warum. Wenn es ein Scoping-Problem ist, wie kann es den Typ selbst identifizieren? Wäre der Typ selbst nicht außerhalb des Geltungsbereichs? Ist es so, als ob nur die Eigenschaften des Typs außer Reichweite sind? Das scheint seltsam, denn das bedeutet, dass der Typ zwar abgeleitet werden kann, wir aber nicht auf seine Eigenschaften zugreifen können, wenn nicht explizit angegeben. – leoOrion