GithubHelp home page GithubHelp logo

Isolate bug? about cycle-snabbdom HOT 41 CLOSED

tylors avatar tylors commented on June 11, 2024
Isolate bug?

from cycle-snabbdom.

Comments (41)

TylorS avatar TylorS commented on June 11, 2024

Hello @arlair

I browsed through the source of the page you linked, and I didn't see any instances of cycle-scope-*.

The way that isolate works, here in cycle-snabbdom (and the other dom drivers), is it defines 'boundaries'. So if you call isolate() around a component that will create a view, that contains a <div /> and n children, you will end up with a <div class="cycle-scope-1" />. When using DOM.select('.something') from within that component, it is actually calling DOM.select(".cycle-scope-1").select(".something"). This is how isolation in the DOM drivers work currently.

Depending on how many times isolate() itself is called, it will generate new 'ids'.

See: https://github.com/cyclejs/isolate/blob/master/src/index.js#L1-L5

So I see that you're using webpack, my guess (tell me if I'm wrong), is that you're using hot reloading. So one thing that will happen is while hot-reloading, without calling isolate.reset() in your hot-reloading configuration

import isolate from '@cycle/isolate'

const {sinks, sources} = run(main, drivers)

if (module.hot) {
  module.hot.accept()

  module.hot.dispose(() => {
    sinks.dispose()
    sources.dispose()
  })

 isolate.reset() // here
}

You will continue to accumulate the counter inside of @cycle/isolate, which is why you could end up with 16, 17, 18 instead of 1, 2, 3

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Thanks for the reply @TylorS.

It is an interesting idea about the hot reloading, although the demo site I linked is generated with a build script that should use the staging webpack config and not the dev config. On my dev machine I had also turned off hot reloading as I don't think think it was doing anything useful for me and I was having some other issues.

When I inspect the radio element, or do a find in the "Elements" view in Chrome Developer Tools I see the following:

image

I had a debugger break in the code here:
https://github.com/eldarlabs/cycle-ui/blob/master/src/helpers/componentFactory.ts#L12

and could see isolate being called many times, but I only get 3 of the cycle-scopes output. I had been trying to figure out the isolate code in cycle/isolate and cycle-snabbdom, but my understanding is not there yet, ;) I figured it was meant to happen every time it was called, but was not sure if there was some smart logic to omit cycle-scopes if it felt it was not necessary.

I have also tried the following code:

in replace of the above as I mentioned in my initial post

  if (params.props.isolate) {
   if (typeof sources === 'undefined') {
      factory = isolateLocal(factory);
    } else {
      factory = sources.isolate(factory);
    }
  }

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

I just noticed that the components that get the cycle-scope have an empty div. I took out the following on one component:

{ props: { className } },

to make it an empty div and now I get a cycle-scope. It seems passing a className props blats the cycle-scope.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

This could be a bug in my isolation code! Do you think it possible for you to wrangle together a small test (or a sample I could make into a test) ?

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Also, I'm working on using data-cycle-isolate='scope' instead of using a className to begin with!

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Is there a basic cycle-snabbdom example repo somewhere I could fork?

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Not that I know of, though you can use this as your starting point

http://esnextb.in/?gist=20a8535207697afa14eb7ee960db94d7

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

@TylorS Okay, try this out:
http://esnextb.in/?gist=29991688d608ddbadbc07706b5c77f86

I see:
image

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Thanks @arlair - I in fact can reproduce using that. An interesting bit is if you use the selector instead of props, it works as you'd expect. I'm going to assume that this is an issue with cycle-snabbdom until I can investigate further.

http://esnextb.in/?gist=d374c0dcfdcd322167671bd6dfbdd4a3

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Ahh, interesting. I use https://github.com/JedWatson/classnames in my components to create a varying number of classes. I tend to use the props version so I don't need to modify the selector version to include a '.' and formatting it to fit the selector format.

I guess there isn't much point fixing this if it will be replaced with the data-* isolation, but having a test that covers the different options might be useful.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

@arlair Interestingly, this may not be cycle-snabbdom bug per se. http://esnextb.in/?gist=d374c0dcfdcd322167671bd6dfbdd4a3

The props className overrides the usage of one by the selector. The DOM drivers use the selector to append the className to the vnode currently. So it seems that the 2 simply cannot coexist :(

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Very interesting. A strange case. I remember considering a while back about removing support for selector in my components as being able to define it in two places is a bit confusing and partly because it made the overloading TypeScript method more complex. Overloading optional parameters in TypeScript is not very nice to implement :(

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

<-- secretly not a TypeScript fan

Yeah, working with TypeScript can be a pain when you begin to do anything remotely complex.

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Haha, I'm not a fan of JavaScript ;). Unfortunately, TypeScript has to compile to JavaScript underneath which limits some of the things it can do. Optional parameters are horrible in TypeScript because they are horrible in JavaScript ;)

I find adding types and interfaces highlight issues in existing code bases and reduces bugs as I write. I also find it easier to understand code the code with types. However, I can understand why people can find them tedious, but I think they pay you back in the long term :).

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Don't get me wrong, I love types, and would love having a strongly-typed language.
I'd love to use Elm (or something similar), but I'd miss Cycle too much!

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Thank you for opening this today, its made me actually do things 👍

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

#30

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

I was feeling bad as I thought you should have been looking around Copenhagen.

I have no cycle-scopes after trying the branch, although my intents all seem broken as well ;). I will have to check out what is happening.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Wonderful haha. I need to try and test them locally. I haven't yet, just have all the tests working currently.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

http://codepen.io/TylorS/pen/mPjJGX?editors=0010

Really basic, but seems to be working for me here. Will try something better.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

More of a perf test, but http://codepen.io/TylorS/pen/LNBVvL?editors=0010

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Yeah, I get this counter code working in the pen:

http://codepen.io/rationaldev/pen/oxMjgo?editors=0010

I seem to have some issues with some similar code in my own project. I'm trying to cut it down to see where it is going wrong.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

I'm trying to reproduce :)

Let me know if you can share anything that I can debug on!

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Well I expect my own issue might be related to my scoping never having worked in the first place ;) I'm still a little confused as to how isolation works.

If I have some code like this:

  const action$ = $.merge(
    DOM.select('.counter').select('.decrement').events('click').map( (ev: any) => -1),
    DOM.select('.increment').events('click').map( (ev: any) => +1)
  );
  let count$ = action$.startWith(0).scan((x: any, y: any) => x + y);
  return {
    DOM: count$.map(count =>
        div('.counter', [
          Button(sources, { isolate: true, className: 'decrement', label: 'Decrement' }).DOM,
          Button(sources, { isolate: true, className: 'increment', label: 'Increment' }).DOM,
          p('Counter: ' + count)
        ])
      )
  };

How can I target a Button component if it is isolated. Do I need to go down the tree at each level by classname like:

DOM.select('.counter').select('.decrement').events('click').map( (ev: any) => -1),

or can I get straight to what I want with:

DOM.select('.increment').events('click').map( (ev: any) => +1)

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

I tried putting the buttons into their own variables, but that doesn't help:

const incrementButton = Button(sources, { isolate: true, className: 'increment', label: 'Increment' });

If I make isolate false on both buttons they work using either select method.

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

I can also get events on both isolated buttons with

DOM.select('.counter').events('click').map( (ev: any) => -1),

but I can't figure out how to target their events individually. I want them isolated so they don't interfere with each other.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Could you share the code for the Button and how isolation is being supplied?

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Sure.

Button:
https://github.com/eldarlabs/cycle-ui/blob/master/src/button/Button.ts

Isolation is enabled from the props, but the default isolation for Button is true.
https://github.com/eldarlabs/cycle-ui/blob/master/src/helpers/componentFactory.ts#L12

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Although I have actually changed the isolation code to pass the isolation function it in via the sources.

  if (params.props.isolate) {
   if (typeof sources === 'undefined') {
      factory = isolateLocal(factory);
    } else {
      factory = sources.isolate(factory);
    }
  }

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

I don't see anything apparent to me at the moment as to why its not working for you.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

http://codepen.io/TylorS/pen/MyBado?editors=0010

I'm still having no issues ATM

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

I changed it back to always use local isolate (ie, not passed through from sources and imported in the file, just in case it was being messed with by isolation of the sources) and now only the decrement button works, but not the increment even though they are using the same selection method of going down the vtree. I also had to call isolate on the whole Counter component or else neither button works.

DOM.select('.counter').select('.decrement').events('click').map( (ev: any) => -1),
DOM.select('.counter').select('.increment').events('click').map( (ev: any) => +1)

Oh, I was thinking I should make a pen to simplify it, but looks like you already have. I will have a play with what you just sent. Thanks.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

http://codepen.io/TylorS/pen/wGxMvG?editors=0010

This example makes heavy use of isolate()

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Ahh, you are passing the click$ out of the Button in your example. I had wondered the other week if that is the only way to get the events out of an isolated component. I hope not, as that would mean every isolated component would have to pass out every type of event it could provide for external consumption.

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

I think this shows what I was trying to do, but I'm not sure it is allowed with the current isolation library. It works if you take out the isolation on the buttons. I'm trying to achieve the buttons being isolated by default so they don't mess with each other or other components, but for their events to be available when I ask for them specifically from an ancestor.
http://codepen.io/rationaldev/pen/LNBGxv?editors=0010

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Yeah so the isolation semantics in the DOM drivers currently (for better or worse), purposefully make sure that parents can not query inside of isolated components like that.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

The way Cycle tries to do things, is to make things very explicit, so passing a click$ from an isolated component is very normal and encouraged. If you need/want to do things by assigning and querying classNames (which really is a form of isolation, perhaps more explicit) like that, there really is no need for isolate()

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Ok, thanks for your patience getting me to this point :).

I'm not sure how that works for a generic UI library like I was trying to build where potentially many events are possible for a component, but they can't interplay with each other with their internal intents. It seems like I only want partial isolation ;). I'm a bit confused now, so I guess I'll have to mull over whether I can do what I was trying to achieve :) Cheers.

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Ok, thanks for your patience getting me to this point :).

Certainly, my pleasure.

It seems like I only want partial isolation

There have been chats about changing the way that isolate() works.

I've had some chats today, and I've been thinking of something along the lines of making it opt-out-able (not a word).

Something like DOM.select('.whatever').events('click', {own: false}) Where it wouldn't filter out childrens events, but would likely default to true still for backwards compatibility.

Then likewise, I think there would need to be a change to .observable, I think something like
DOM.select('.something').elements({own: false}) where own would true by default yet again here.

from cycle-snabbdom.

arlair avatar arlair commented on June 11, 2024

Yes, I have followed a lot of the online chats, but it still confuses me ;)

I think what I envisaged is components don't extend outside themselves by default, which is what I was trying to achieve by defaulting isolate to true. But I still want to be able to explicitly communicate with other components without exporting the HTML specification from each component ;)

from cycle-snabbdom.

TylorS avatar TylorS commented on June 11, 2024

Another thing related to the original issue here - snabbdom/snabbdom#103 (comment)

from cycle-snabbdom.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.