Open brodycj opened 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.
Makes sense, thanks. A couple more thoughts that are likely going off-topic:
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)
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.
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.
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.
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.
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.
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
such as:
and some native view frameworks from #3: