composi / core

A JavaScript library for creating websites, PWAs and hybrid apps.
MIT License
27 stars 2 forks source link

[question] use with other libraries #2

Open brodycj opened 5 years ago

brodycj commented 5 years ago

such as:

and some native view frameworks from #3:

rbiggs commented 5 years ago

Composi shares some features externally with React because of the use of JSX. This provides JSX features such as props to pass data down like in React. It has a virtual DOM as well with a reconciliation (diffing) algorithm. Composi lacks class components. It has function components, but with a twist. They support lifecycle hooks similar to the ones React class components have. But they are implemented at the element level. Composi lifecycle hooks are for tracking lifecycle of an element in a component--not the component itself. This makes sharing components and other features between React and Composi fundamentally challenging. Also Composi uses a state management system derived from the Elm Architecture, which is simpler than the React/Redux duopoly. I have looked at NativeScript in the past. Since it supports vanilla JavaScript, you should be able to use that with Composi. To be honest, I haven't had the motivation to dig too deeply into it. It would probably be better to create a wrapper for NativeScript like the Angular and Vue ones that would allow Composi's state management to trigger updates automatically in NativeScript. To pull of NativeScript support I'd need help from somebod(y/ies) with some experience and familiarity with it.

brodycj commented 5 years ago

Makes sense, thanks. A couple more thoughts that are likely going off-topic:

rbiggs commented 5 years ago

Well, technically lifecycle hooks are not events. That's why I call them hooks. The just look like events due to the React precedence. They are actually just JSX attributes that exist on the virtual nodes. They never become anything real in the real DOM.

You mention "make more abstract API layers". I suppose you're talking about Composi? If so, the state management runtime is already quite agnostic. The render function just passes state to whatever you want to use to render it with. By default Composi uses its own render function, but you could use it for React, Vue, or whatever. Here is an example of Composi state management using React to render a function component that uses React hooks (useEffect):

import React from 'react';
import { render } from './utils'
import { run } from '@composi/core'
import { List } from './components/list'
import { actions } from './effects/actions'
import { batchedSubscriptions } from './effects/subscriptions'

const program = {
  init() {
    return [null]
  },
  view(state, send) {
    return state && render(<List {...{state, send}} />, 'section');
  },
  update(state, msg, send) {
    return actions(state, msg, send)
  },
  subscriptions(state, send) {
    return batchedSubscriptions
  }
}

run(program)
brodycj commented 5 years ago

By default Composi uses its own render function, but you could use it for React, Vue, or whatever.

+1, wouldn't mind some more documentation on this

Here is an example of Composi state management using React to render a function component that uses React hooks [...]

Is there an example somewhere?

I would like to take a look at this kind of thing, may give it a try with React Native.

rbiggs commented 5 years ago

OK, just uploaded this project: https://github.com/composi/list-react

It was created with create-react-app. I added Composi as a dependency. The components are React 16 functional components using React hooks. It has a Composi program that uses Composi's run function to create state management, which is handled with actions and effects, etc. The program's view method uses React's render method to render the React component when state changes. The React components are sending messages just like Composi components would. These get processed by the Composi program's update method. Just look at the src/index.js file to see how the two work together.

rbiggs commented 5 years ago

When this project first runs, a subscription launches that fetches initial data from a JSON file in the public/data folder. It also uses the Composi module @composi/idb, which is a simple promise-based wrapper I made for IndexedDB. This makes using IndexedDB as easy as using localStorage. I use @composi/idb to persist data locally when the user adds or deletes items. Add some items. The reload the browser or quite the browser and relaunch it. You'll see the new items have indeed been saved to IndexedDB. To handle fetching and persisting data there are new messages: useFetchedData and saveLocally, and corresponding actions to handle these. Hope that makes it clear what's going on in this project for you.

rbiggs commented 5 years ago

By the way, this project is basically the same as the full Composi project: https://github.com/composi/examples/tree/master/2-complex%20projects/4-todo-list. The Composi project has a total JavaScript payload of 23KB minified. This React version has a total JavaScript payload of 126KB minified.

brodycj commented 5 years ago

Thanks @rbiggs. I gave it a try yesterday, had some trouble porting to React Native since it seem to use very modular CSS. I hope to take another look, someday.

rbiggs commented 4 years ago

As an update to this issue, I've created a version of @composi/core that is just the state manage, along with tagged unions and batched effects.It weighs in a about 600 kb. It's available from npm:

npm I -D @composi/runtime

Github repo: https://github.com/composi/runtime

You can use React as the render, as in this repo: https://github.com/composi/list-react And here's an example of @composi/runtime with Lit-Html: https://github.com/composi/list-lit-html

Documentation is the same as regular runtime of @composi/core: https://composi.github.io/en/docs/runtime/runtime.html