简单的历史推送崩溃
Crash with simple history push
只是想尝试一些愚蠢的东西,然后玩弄 Cycle.js。并且 运行 出现问题。基本上我只有一个按钮。当您单击它时,它会将该位置导航到一个随机散列并显示它。几乎像一个愚蠢的路由器 w/o 预定义路由。 IE。路线是动态的。同样,这不是什么实用的东西,我只是在弄乱一些东西并尝试学习 Cycle.js。但是在我单击 "Add" 按钮后,下面的代码崩溃了。但是位置已更新。如果我实际上只是导航到“#/asdf”,它会显示带有 "Hash: #/asdf" 的正确内容。不确定流程为何因错误而崩溃:
render-dom.js:242 TypeError: 无法读取 属性 'subscribe' of undefined(…)
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')
});
感谢您的帮助
在函数 CreateButton
上,您将点击映射到 history.push()
而不是将其映射到导致 error:
function CreateButton({ DOM }) {
...
const vtree$ = create$.map(rs => rs
? history.push(`/${rs}`) // <-- not a vtree
: button('.create-button .btn .btn-default', 'Add')
);
...
}
相反,您可以使用 do 运算符 来执行哈希更改:
function CreateButton({ DOM }) {
const create$ =
...
.do(history.push(`/${rs}`)); // <-- here
const vtree$ = Observable.of(
button('.create-button .btn .btn-default', 'Add')
);
...
}
但是在函数式编程中你不应该对你的应用程序逻辑产生副作用,每个函数都必须保留pure. Instead, all side effects should be handled by drivers. To learn more take a look at the drivers section on Cycle's documentation
要在消息末尾看到正在运行的驱动程序跳转。
此外,在您的 main
函数中,您没有使用流来呈现 vtree。它不会对 locationHash 更改做出反应,因为 vtree$ = hash ? ... : ...
仅在应用程序引导时评估一次(当评估主要功能并且 "wires" 每个流在一起时)。
一项改进是声明您的 main
的 vtree$ 如下,同时保持相同的逻辑:
const vtree$ = hash$.map((hash) => hash ? ... : ...)
这是一个带有小型 locationHash 驱动程序的完整解决方案:
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: 你的 randomstring
函数名称有错字,我在我的例子中修正了它。
我进一步建议使用@cycle/history 来更改路线
(只显示相关部分)
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),
})
只是想尝试一些愚蠢的东西,然后玩弄 Cycle.js。并且 运行 出现问题。基本上我只有一个按钮。当您单击它时,它会将该位置导航到一个随机散列并显示它。几乎像一个愚蠢的路由器 w/o 预定义路由。 IE。路线是动态的。同样,这不是什么实用的东西,我只是在弄乱一些东西并尝试学习 Cycle.js。但是在我单击 "Add" 按钮后,下面的代码崩溃了。但是位置已更新。如果我实际上只是导航到“#/asdf”,它会显示带有 "Hash: #/asdf" 的正确内容。不确定流程为何因错误而崩溃:
render-dom.js:242 TypeError: 无法读取 属性 'subscribe' of undefined(…)
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')
});
感谢您的帮助
在函数 CreateButton
上,您将点击映射到 history.push()
而不是将其映射到导致 error:
function CreateButton({ DOM }) {
...
const vtree$ = create$.map(rs => rs
? history.push(`/${rs}`) // <-- not a vtree
: button('.create-button .btn .btn-default', 'Add')
);
...
}
相反,您可以使用 do 运算符 来执行哈希更改:
function CreateButton({ DOM }) {
const create$ =
...
.do(history.push(`/${rs}`)); // <-- here
const vtree$ = Observable.of(
button('.create-button .btn .btn-default', 'Add')
);
...
}
但是在函数式编程中你不应该对你的应用程序逻辑产生副作用,每个函数都必须保留pure. Instead, all side effects should be handled by drivers. To learn more take a look at the drivers section on Cycle's documentation
要在消息末尾看到正在运行的驱动程序跳转。
此外,在您的 main
函数中,您没有使用流来呈现 vtree。它不会对 locationHash 更改做出反应,因为 vtree$ = hash ? ... : ...
仅在应用程序引导时评估一次(当评估主要功能并且 "wires" 每个流在一起时)。
一项改进是声明您的 main
的 vtree$ 如下,同时保持相同的逻辑:
const vtree$ = hash$.map((hash) => hash ? ... : ...)
这是一个带有小型 locationHash 驱动程序的完整解决方案:
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: 你的 randomstring
函数名称有错字,我在我的例子中修正了它。
我进一步建议使用@cycle/history 来更改路线 (只显示相关部分)
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),
})