Skip to content
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

Any practical apps using this? #1

Open
dumblob opened this issue Mar 15, 2021 · 5 comments
Open

Any practical apps using this? #1

dumblob opened this issue Mar 15, 2021 · 5 comments

Comments

@dumblob
Copy link

dumblob commented Mar 15, 2021

Hi, I'm a freak into UI libs and especially "live variables" (as I myself call it - be it a stream/signal/pubsub/...) which solve like 50% of problems one has when using UI libs.

I was following S's development for some time and today I got your message about anod.

My first impression (without even trying it out) is very good. Kudos!

Do you have any real apps using it? I'd be interested especially in performance issues on mobile devices (e.g. with long lists, many widgets with such "live information", etc.).

Btw. how would you approach building a WhatsApp-like "infinite" feed of messages with anod efficiently? Would it be difficult (including the ability to add, change and delete arbitrary messages at arbitrary positions)?

Would anod handle even some animations on mobile devices?

Are there any issues if having arbitrarily "nested" (or should I say "chained"?) data() with value() etc.? Correctness issues? Performance issues? Other issues?

@visj
Copy link
Owner

visj commented Mar 16, 2021

Thanks for the recognition!

Firstly, development of anod is still very early stage. I am pretty certain no apps are using it, I just recently pushed the first version to Github.

Also, anod is like S only a reactive library. I'm tinkering a bit with a UI library on top of anod here. The idea there is to build basically a merge between ivi and surplus, e.g. building the entire dom using document.createElement, and then mounting computations that patch updating parts of the view. I am experimenting with using a virtual dom tree for diffing as it handles complex data much better than having raw dom nodes.

For example, if you have something like this:

[1,2,3].map(x => [div(), div()]);

And then start to move around dom nodes, many libraries flatten out nodes and diff them instead of diffing the fragment parts.

Btw. how would you approach building a WhatsApp-like "infinite" feed of messages with anod efficiently? Would it be difficult (including the ability to add, change and delete arbitrary messages at arbitrary positions)?

Given the mutation driven approach anod uses, it should shine on any operation where you're not re-rendering data such as from a server, but rather applying mutations on an array. Basically, if what you're doing is push, insertAt, removeAt, move or similar, the idea is that anod should perform better than vanilla javascript itself. However, if what you're doing is patching data from the server, e.g. you have some data [1,2,3,4,5] and then you update it with a new array as [3,4,2,1,5], the goal is to have anod on par with existing libraries, but it's unlikely to outperform them.

Anod is a merge of S.js and S-array. It differs mainly in two ways: conditional rendering and array mutation propagation. The core reactivity library is identical to S with the notable exception of flag operations. It was good that you asked, I will add this to the docs.
Basically, anod accepts four flags: Flag.Wait, Flag.Trace, Flag.Static, Flag.Dynamic.
Flag.Wait is the same as onchanges in S. Flag.Trace means that a computation will not fire changes unless the value changes. Anod uses this internally for all array operations, such as the example below:

import { array, tie } from 'anod';
let ds = array([1,2,3,4,5]);
let cs = ds.some(v => v === 9);
tie(() => { console.log(cs()); }, void 0, Flag.Wait);
ds.push(6); // This operation is O(1), anod only checks if the added element matches
ds.insertRange(2, [7,8]); // This operation also only checks added items
ds.pop(); // This operation notes that cs is false and deletion occurs and returns
ds.push(9); // Now value of cs has changed, so here we log to the console

Flag.Static means that you can setup a static dependency tree without explicitly specifying the dependencies. E.g. if you run a computation and read signals, it marks the computation node as final and afterwards does not reconstruct the dependency tree.

@dumblob
Copy link
Author

dumblob commented Mar 16, 2021

Also, anod is like S only a reactive library. I'm tinkering a bit with a UI library on top of anod here. The idea there is to build basically a merge between ivi and surplus, e.g. building the entire dom using document.createElement, and then mounting computations that patch updating parts of the view. I am experimenting with using a virtual dom tree for diffing as it handles complex data much better than having raw dom nodes.

That might be a viable approach. What proved as the most efficient approach from my experience is to design UI libs from top to bottom (i.e. not from buttom to top as DOM-focused libs etc. do). With top to bottom I mean having a set of widgets - some of them instantiated from the very start of the app, some not (some of these non-instantiated are already "constructed" and just hardwired in code behind a wall of if-then-else but some of these are even being "thought up"/constructed dynamically in runtime and then wired dynamically in runtime).

Imagine the use case I outlined in vlang/ui#7 (comment) (and clarified in vlang/ui#7 (comment) ). This of course requires full dependency tree reconstruction.

Overall it sounds very promising! Keep me posted (I'm already subscribed to isolit).

@dumblob
Copy link
Author

dumblob commented Mar 16, 2021

Btw. you might want to look at how "live variables" can be utilized everywhere and what advantages it brings:

@visj
Copy link
Owner

visj commented Mar 16, 2021

That's a very interesting approach. But my main goal of isolit is actually not performance but simplicity, so I think the goal of the project actually sidesteps a bit from your vision. It's definitively possible to try and design another library that is more bare metal.

The idea of isolit is to allow the user to simply use pure functions for any conditional rendering, and directly mapping anod lists whenever you have dynamic children.

The DSL is thought to look something like this:

const ds = data(true);
const App = () => (
  div(_, { id: 'root' }, [
    () => ds() ? button(_, _, 'Active') : null,
    ul(_, _, uls.map(u => li(_, _, 'List item')),
  ])
);

@dumblob
Copy link
Author

dumblob commented Mar 16, 2021

Even if it looks a bit differently than the vision I outlined, it's still very interesting, so I'll try to follow your steps 😉.

Feel free to close this issue if you think there is not much more to add here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants