2016-03-28 12 views
0

nur versuchen, albern Sachen und herumspielen mit Cycle.js. und auf ein Problem stoßen. Im Grunde habe ich nur einen Knopf. Wenn Sie darauf klicken, wird der Standort zu einem zufälligen Hashwert navigiert und angezeigt. Fast wie ein dummer Router ohne vordefinierte Routen. Ie. Routen sind dynamisch. Wiederum ist das nichts Praktisches. Ich bin nur mit ein paar Sachen beschäftigt und versuche Cycle.js zu lernen. Aber der folgende Code stürzt ab, nachdem ich auf "Hinzufügen" geklickt habe. Der Standort wird jedoch aktualisiert. Wenn ich nur zu "#/asdf" navigiere, wird der korrekte Inhalt mit "Hash: #/asdf" angezeigt. Nicht sicher, warum der Fluss mit Fehler abstürzt:Crash mit einfacher Geschichte Push

render-dom.js: 242 Typeerror: kann nicht lesen Eigenschaft 'subscribe' undefinierte (...)

import Rx from 'rx'; 
import Cycle from '@cycle/core'; 
import { div, p, button, makeDOMDriver } from '@cycle/dom'; 
import { createHashHistory } from 'history'; 
import ranomdstring from 'randomstring'; 

const history = createHashHistory({ queryKey: false }); 

function CreateButton({ DOM }) { 
    const create$ = DOM.select('.create-button').events('click') 
    .map(() => { 
     return ranomdstring.generate(10); 
    }).startWith(null); 

    const vtree$ = create$.map(rs => rs ? 
    history.push(`/${rs}`) : 
    button('.create-button .btn .btn-default', 'Add') 
); 

    return { DOM: vtree$ }; 
} 

function main(sources) { 
    const hash = location.hash; 
    const DOM = sources.DOM; 

    const vtree$ = hash ? 
    Rx.Observable.of(
     div([ 
     p(`Hash: ${hash}`) 
     ]) 
    ) : 
    CreateButton({ DOM }).DOM; 

    return { 
    DOM: vtree$ 
    }; 
} 

Cycle.run(main, { 
    DOM: makeDOMDriver('#main-container') 
}); 

Danke für die Hilfe

Antwort

2

auf Ihrer Funktion CreateButton Sie kartieren Ihre Klicks auf history.push() statt Mapping es zu einem vtree die der Fehler verursacht:

function CreateButton({ DOM }) { 
    ... 
    const vtree$ = create$.map(rs => rs 
    ? history.push(`/${rs}`) // <-- not a vtree 
    : button('.create-button .btn .btn-default', 'Add') 
); 
    ... 
} 

Stattdessen könnten Sie den Bediener tun verwenden die hashchange auszuführen:

function CreateButton({ DOM }) { 
    const create$ = 
    ... 
    .do(history.push(`/${rs}`)); // <-- here 

    const vtree$ = Observable.of(
    button('.create-button .btn .btn-default', 'Add') 
); 
    ... 
} 

jedoch in der funktionalen Programmierung Sie keine Nebenwirkungen auf Sie app Logik ausführen soll, muss jede Funktion pure bleiben. Stattdessen sollten alle Nebenwirkungen von Treibern behandelt werden. Um mehr zu erfahren, werfen Sie einen Blick auf die drivers section on Cycle's documentation

Um einen funktionierenden Treiber zu sehen springen am Ende der Nachricht.


Außerdem auf Ihrer main Funktion Sie nicht Ströme wurden mit Ihrem vtree zu machen. Es wäre nicht auf locationHash-Änderungen reagiert worden, weil vtree$ = hash ? ... : ... nur einmal beim App-Bootstrapping ausgewertet wird (wenn die Hauptfunktion ausgewertet wird und alle Ströme zusammen "verdrahtet").

wird eine Verbesserung Ihrer main ‚s vtree $ wie folgt zu erklären, während die gleiche Logik zu halten:

const vtree$ = hash$.map((hash) => hash ? ... : ...) 

Hier ist eine komplette Lösung mit einem kleinen locationHash Treiber:

import Rx from 'rx'; 
import Cycle from '@cycle/core'; 
import { div, p, button, makeDOMDriver } from '@cycle/dom'; 
import { createHashHistory } from 'history'; 
import randomstring from 'randomstring'; 


function makeLocationHashDriver (params) { 
    const history = createHashHistory(params); 

    return (routeChange$) => { 
    routeChange$ 
     .filter(hash => { 
     const currentHash = location.hash.replace(/^#?\//g, '') 
     return hash && hash !== currentHash 
     }) 
     .subscribe(hash => history.push(`/${hash}`)); 

    return Rx.Observable.fromEvent(window, 'hashchange') 
     .startWith({}) 
     .map(_ => location.hash); 
    } 
} 

function CreateButton({ DOM }) { 
    const create$ = DOM.select('.create-button').events('click') 
    .map(() => randomstring.generate(10)) 
    .startWith(null); 

    const vtree$ = Rx.Observable.of(
    button('.create-button .btn .btn-default', 'Add') 
); 

    return { DOM: vtree$, routeChange$: create$ }; 
} 

function main({ DOM, hash }) { 
    const button = CreateButton({ DOM }) 
    const vtree$ = hash.map(hash => hash 
    ? Rx.Observable.of(
     div([ 
      p(`Hash: ${hash}`) 
     ]) 
    ) 
    : button.DOM 
) 

    return { 
    DOM: vtree$, 
    hash: button.routeChange$ 
    }; 
} 

Cycle.run(main, { 
    DOM: makeDOMDriver('#main-container'), 
    hash: makeLocationHashDriver({ queryKey: false }) 
}); 

PS: Es ist ein Tippfehler in Ihrem randomstring Funktionsname, ich habe es in meinem Beispiel behoben.

+0

Ahh, die Sinn macht. Sollte es herausgefunden haben. Danke Hilfe geschätzt! – Bojan

5

würde ich weiter vorschlagen @ Zyklus/Geschichte mit Ihrem Weg zu tun zu wechseln (nur relevante Teile zeigt)

import {makeHistoryDriver} from '@cycle/history' 
import {createHashHistory} from 'history' 

function main(sources) { 
    ... 
    return {history: Rx.Observable.just('/some/route') } // a stream of urls 
} 

const history = createHashHistory({ queryKey: false }) 
Cycle.run(main, { 
    DOM: makeDOMDriver('#main-container'), 
    history: makeHistoryDriver(history), 
}) 
+0

Hallo, danke für die Rückmeldung. Tut mir leid, ich fühle mich wirklich dumm, aber ich konnte es nicht mit @ cycle/history arbeiten; Ich habe verschiedene Dinge ausprobiert und die Dokumentation gelesen. Wie verbinde ich den Verlaufstreiber mit den Änderungsereignissen der Schaltfläche? Soll ich die beiden Ströme kombinieren? – Bojan

+0

Hmm Ich denke, ich habe es endlich herausgefunden, danke für die Hilfe. – Bojan