-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Component runs twice, isolated child components lose scope/namespace #95
Comments
https://github.com/wyqydsyq/hapi-cycle/blob/master/src/ui/app.js#L10 I haven't tried your code but you def need to multicast your See example doing this here: |
Ah right I was just going by the example on the readme which doesn't mention it needing to be multicast (though it makes sense that it should be, someone new to Cycle/xstream like myself wouldn't think of that). So I guess the only actionable thing from this issue is to mention that in the docs. Sorry I'm not sure what you mean by sinks making independent closure chains, could you please further explain or give an example of this? Thanks. |
Sure. I was being too wordy. If you understand that it needs to be multicast then you understood my point. For completeness though, the below code will create an object but it won't start emitting until
When you call Each call to
|
Actually, I just remembered |
Using Either way it seems this is indeed an xstream bug, but I've only been able to reproduce it when using cyclic-router so far. |
Hi guys, thanks for the conversation here! I've been very busy and haven't been able to give this repo much love. PRs are graciously welcomed. Let me know if you would like to be added as a collaborator, I can also probably add you to npm to do new publishes 👍 |
So I put the app I'm having this issue with up on Heroku and have found something pretty strange - using If you look at the console when initially loading the page (or clicking one of the buttons that changes the current route) you'll see it's logging component names, and doing it multiple times. These are just from a single But when running this exact same app locally, with the same webpack config, the issue doesn't happen and the output is logged once per component. I'm still trying to make sure this isn't just an error on my part, and pin down where this is happening so I can write a reproducible test/example of it. But it really boggles me as to why it's working for me on localhost in latest browsers, but not at all in older browsers or when served from Heroku. I assumed something in my webpack config/build was breaking it, but even with doing a webpack build with |
@wyqydsyq I dunno. I love the goals of xstream, and I've used it a lot, but it is young and def has some bugs. If you have the patience to endure and investigate this issue among others, cool. Otherwise I recommend you switch to another stream library and see if that fixes it. |
Apologies for slow response here, and thank you for the discussion. I currently do not have the time to investigate this. I would love for some help and a community contribution. |
@wyqydsyq As a potential workaround you could ensure that isolate is only called once, but this may have other issues if you try to use the component multiple times as sibilings to one another. - export default sources => isolate(Component)(sources)
+ const isolatedComponent = isolate(Component)
+ export default sources => isolatedComponent(sources) |
@TylorS I'd love to be a collaborator, but I don't have anything to contribute yet! Cyclic-router does what I need for now. If I need a feature it doesn't have I'll def ping you abt it and collaborate for sure. :) I find this lib very useful. |
@ntilwalli yeah I might switch to most for the time being since it's API is closer to xstream than Rx (plus I wasn't a fan of using Rx back when it was the default for Cycle) but will still try to help track this bug down. @TylorS thanks for the suggestion, that did help with single isolated components (e.g. the add user form) but I'm also using https://github.com/cyclejs/collection (for listing users) which I can't really apply this work-around to since it seems that library automatically isolates child components behind the scenes. |
One thing I just noticed is that it doesn't seem to be just re-calling the routed component once, it calls the component once per each sink I'm mapping over from the router, so for example when I added a Edit: I just made a test driver to check this and it started logging to console 4 times, so it's definitely calling the routed component once per sink wyqydsyq/hapi-cycle@efc95d1 |
Alright, now this is some super bizarre shit. Adding This commit exhibits the issue: This doesn't: This really confuses me because according to the xstream docs, |
There's an issue associated with |
Am not sure if this is related, kind apologies in advance if it isn't. I came across this after applying Any way here is a watered down version to reproduce {
"dependencies": {
"@cycle/dom": "^17.1.0",
"@cycle/history": "^6.1.0",
"@cycle/isolate": "^2.1.0",
"@cycle/run": "^3.1.0",
"cyclic-router": "^4.0.3",
"history": "^4.6.1",
"object-assign": "^4.1.1",
"switch-path": "^1.2.0",
"xstream": "^10.6.0"
},
} import xs from "xstream";
import assign from "object-assign";
import {run} from "@cycle/run";
import {makeDOMDriver, div, a, span} from "@cycle/dom";
import {makeHistoryDriver, captureClicks} from "@cycle/history";
import {RouterSource} from "cyclic-router/lib/RouterSource";
import {createBrowserHistory} from "history";
import switchPath from "switch-path";
const makeRouterDriver = (history, routerMatcher) => {
const historyDriver = captureClicks(makeHistoryDriver(history))
return sink$ => {
const history$ = historyDriver(sink$).remember()
return new RouterSource(history$, [], history.createHref, routerMatcher)
}
}
const makeRouter = routes => {
return sources => {
const match$ = sources.router.define(routes)
const page$ = match$
.map(({path, value}) => {
return value(assign({}, sources, {router: sources.router.path(path)}))
})
return {
DOM: page$.map(c => (c.DOM || xs.never())).flatten(),
HTTP: page$.map(c => (c.HTTP || xs.never())).flatten(),
router: page$.map(c => (c.router || xs.never())).flatten(),
storage: page$.map(c => (c.storage || xs.never())).flatten(),
};
}
};
const makeRandom = () => Math.round(Math.random() * 100)
const Main = makeRouter({
'/home': sources => {
const id = makeRandom();
const detail = HomeRouter(sources)
return {
DOM: detail.DOM.map(detail => div([
div(['Home ' + id]),
div([
a({attrs: {href: '/home/dashboard'}}, 'Dashboard'),
span(' - '),
a({attrs: {href: '/home/settings'}}, 'Settings'),
]),
detail
]))
}
},
'*': sources => {
return {
DOM: xs.of(div([
'Not Found',
div([
a({attrs: {href: '/home/dashboard'}}, 'Dashboard'),
span(' - '),
a({attrs: {href: '/home/settings'}}, 'Settings'),
]),
]))
}
}
})
const HomeRouter = makeRouter({
'/dashboard': sources => {
const id = makeRandom();
return {
DOM: xs.of(div('Dashboard ' + id))
}
},
'/settings': sources => {
const id = makeRandom();
return {
DOM: xs.of(div('Settings ' + id))
}
},
})
const drivers = {
DOM: makeDOMDriver('#app'),
router: makeRouterDriver(createBrowserHistory(), switchPath),
}
run(Main, drivers) Notice how the id value in the main changes every time you click the links. The links open nested components, shouldn't the main component run only once (thus maintain the same value) ? Has anyone discovered a way around this? |
I have an app with a bunch of nested components and have found that when I use cyclic-router, the component that's being loaded (
Welcome
) gets called twice, causing isolated child components with implicit scopes (e.g.export default sources => isolate(UserProfile)(sources)
) lose track of their scope because it seems the scopes are recalculated when the component is reran.If you
git clone
https://github.com/wyqydsyq/hapi-cycle, runnpm install && npm run launch
and then visit http://localhost:1337/ you can see the UI in this case works fine, but if you then swap the part of https://github.com/wyqydsyq/hapi-cycle/blob/master/src/ui/app.js that returns just the component with the commented out lines to make it use cyclic-router instead of calling the component directly, subcomponents will no longer emit/recieve events from/to themselves.Using explicit scopes seems to remedy this, as each isolated child component would be using the same scope string in between calling the main component, but that's more of a band-aid fix than a solution.
So the working/not working cases for me are:
The text was updated successfully, but these errors were encountered: