justin-schroeder / arrow-js

Reactivity without the framework
https://arrow-js.com
MIT License
2.33k stars 50 forks source link

Client side router #3

Open ansarizafar opened 1 year ago

ansarizafar commented 1 year ago

Arrow looks promising. Is there any plan to build a client side router or an adapter for TankStack router TanStack/router ?

sifferhans commented 1 year ago

He mentioned routing in the documentation, as I imagine client-side routing might increase the library quite a bit 😊

ansarizafar commented 1 year ago

Router is a key part of a web application. It can be build separately and not as part of core library or an adapter for TankStack router TanStack/router

justin-schroeder commented 1 year ago

Personally i'd be interested in using Remix router with ArrowJS at some point — something akin to what @brophdawg11 has been doing with https://github.com/brophdawg11/remix-routers and vue/svelte

justin-schroeder commented 1 year ago

For the foreseeable future this will be considered out of scope.

brophdawg11 commented 1 year ago

This has been tickling the back of my brain for a little while. The basic wire up is pretty straightforward given Arrow's reactivity. The "tricky" part not handled by the @remix-run/router (and this is true for react-router/remix-router-vue, etc.) is handling the nested routing via an <Outlet /> component so you can render nested routes based on router.state.matches. This then opens up route-scoped useLoaderData() capabilities as well.

Ignoring nested routes though, a simple non-nested UI with Link/Form support clocks in at just over 100 lines including console logs for clarity 😀: https://codesandbox.io/s/remix-router-arrow-js-ncu52c?file=/src/index.js

justin-schroeder commented 1 year ago

I guess its time to build an entire meta framework now 😂

brophdawg11 commented 1 year ago

Not like you don't have enough else to do 😂 ! If you ever dip into SSR don't forget to check out createStaticHandler from @remix-run/router as well. Docs are still pending but it'll handle all the server-side data loading aspects for you.

andymans commented 12 months ago

Nice contribution @brophdawg11 ! I'd been looking at a (now archived but still good) routing solution "roadtrip" - which is actually a strong fit for driving view from state with arrow-js. But, as you've shown, the @remix-run stuff is very interesting too....ahhh dilemmas!!

markmals commented 10 months ago

I've been having fun experimenting with Remix router wrappers for Lit and Preact Signals recently and would love to help with a wrapper for Arrow too! As @brophdawg11 mentioned, to properly handle nested routing (and make some other APIs nicer to use), Arrow will need a context system.

justin-schroeder commented 10 months ago

I’ve actually been thinking about how context could be created in as minimal of a way as possible — nothing to report yet 😂 but I’m open to suggestions. It’s certainly possible for each template to pass it’s parent’s context down via internal call states, but I really want to avoid creating an implicit tree that requires an arrow template as an ancestor. For example, in a perfect world you could:

<dom-element>
  { arrow-template }
    <another-dom-element-not-rendered-by-arrow>
      { arrow-template } <!-- this guy could read context -->
    </another-dom-element-not-rendered-by-arrow>
  {/ arrow-template }
</dom-element>

The above example assumes that <another-dom-element-not-rendered-by-arrow> is a dom element created by some outside force, lets say someone dropped a chunk of old jQuery code right in there, but then a child of that could still pickup context. Crawling parent nodes is horribly inefficient to be a framework feature though and rendering sequencing cannot be guaranteed in this scenario either so an index-based store wouldn’t work. Sounds like a fun problem honestly. More to think on here.

markmals commented 10 months ago

I have two ideas here:

  1. Use custom elements/web components: there is an open standard protocol for cross-framework web component context using event listeners attached to the custom element. You could create custom elements to handle context in a generic way and then wrap them with a more Arrow-friendly function component syntax. This works particularly well for context compatibility across the DOM tree rather than relying on a home-built system, but it does mean adding extra elements to the DOM, which might be okay in some cases but is definitely not in others. I'll experiment with this some this week in relation to the router.
  2. Use the reactive system: Voby does something interesting here: their context system is part of their reactive system (Oby), not their component/templating system. It's built in a way that any code running within a reactive root can access the context, so this might work well for the sort of jQuery-within-an-Arrow-template scenario, but less well with custom elements, which are instantiated by the browser and managed outside of your control.