-
Notifications
You must be signed in to change notification settings - Fork 1
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
Reactivity to state changes #37
Comments
Because PodOs uses rdflib.js, at the moment it is possible for custom components to achieve reactive rendering using callbacks on the graph store.
doUiCallbacks is called on every triple change. It therefore needs to efficiently manage a set of callbacks to individual custom components as well as throttle repeat callbacks in some way. I have a basic buggy implementation of this. |
Given the decision to use rxjs, it makes sense to revisit this callback architecture and identify a solution better suited to PodOs. PodOs core encapsulates rdflib.js so that elements do not depend on it 1 Building on the idea that rxjs provides lazy push collections of multiple values, a possible solution is that the properties of Thing 2 become observables e.g. label is no longer a pull function that returns a value, but is instead a push observable that pos-label reacts to. This would be a major architectural change, which could either be approached as a breaking change, or by PodOS core offering both push and pull architectures for accessing data. However, for devx reasons, I believe PodOs elements should either all be individually reactive to state or not, and I currently believe that making every web component state-reactive is the preferred option. Whatever final architecture is used, I have found that retaining low level access to rdflib.js is often needed given PodOs does not fully cover the rdflib.js api. It would therefore be beneficial for the callback management mechanism to be accessible from custom components, even if direct use is discouraged. There may be other solutions, which is why I've framed this issue as documenting opportunities rather than proposing this as the definitive solution. Footnotes |
As a point of comparison, semantic-ko used observables through the knockoutjs library, though I think PodOS would want to avoid defining an explicit view model. https://web.archive.org/web/20111118042156/http://antoniogarrote.com/semantic_ko/ |
Noting that while external components will use rxjs, reactivity to logged in state (and Webid, and profile) is still managed using a stenciljs store for image, navigation bar, resource and document, with pos-app providing the bridge between rxjs and the store.
|
If I understand correctly, here's an untested proof of concept for an observable rxjs label() used as part of https://github.com/pod-os/PodOS/blob/main/elements/src/components/pos-label/pos-label.tsx @State() label = null;
receiveResource = (resource: Thing) => {
this.resource = resource;
this.resource.label()
.pipe(takeUntil(this.disconnected$))
.subscribe(label=>this.label=label)
};
render() {
return this.label
} However, we also need to deal with destruction of the component similar to PodOS/contacts/src/components/open-address-book/open-address-book.tsx Lines 23 to 33 in 2722676
@State() label = null;
receiveResource = (resource: Thing) => {
this.resource = resource;
this.resource.label()
.pipe(takeUntil(this.disconnected$))
.subscribe(label=>this.label=label)
};
render() {
return this.label
}
private readonly disconnected$ = new Subject<void>();
disconnectedCallback() {
this.disconnected$.next();
this.disconnected$.unsubscribe();
} This seems a bit unwieldy and probably would need to be encapsulated somehow? |
A common framework-specific solution is to proxy object properties to perform dependency-tracking and change-notification when properties are accessed or modified 1 Using stencil-store, we could create a ReactiveThing in PodOS elements, which turns an observable label() into a reactive property, something like (untested): class ReactiveThing {
constructor(thing){
this.disconnected$ = new Subject();
this.state = createStore({
label: null
});
thing.label()
.pipe(takeUntil(this.disconnected$))
.subscribe(label=>this.state.label=label)
};
dispose(){
this.disconnected$.next();
this.disconnected$.unsubscribe();
}
} Which would be used: receiveResource = (resource: Thing) => {
this.resource = new ReactiveThing(resource);
};
render() {
return this.resource.state.label
}
disconnectedCallback() {
this.resource.dispose()
} Footnotes |
SolidOS uses rdflib.js' store.updater.addDownstreamChangeListener. When the remote resource is changed a notification is received via Websocket, the resource is reloaded and a rerender is triggered. https://github.com/search?q=org%3ASolidOS%20addDownstreamChangeListener&type=code |
Thing's interface is reminiscent of https://ldo.js.org It uses a subscribable RDF dataset that emits events for specific quad matches, which triggers rerender of the react component, apparently by updating a forceUpdateCounter state variable.
useSubject appears to be an equivalent of Thing/ReactiveThing |
Opening this issue to document opportunities for components to react to state changes, building on the rxjs decision:
PodOS/docs/decisions/0009-introduce-rxjs.md
Line 19 in 7d2693a
By state changes, I firstly have in mind cases where the triples affecting a subject or object change, either because of another component on the same page or due to data changes.
The primary use case is to perform reactive rendering.
It will likely be desirable to standardise how this is dealt with across solid web components. See https://github.com/solid-contrib/web-components/wiki/Rendering
e.g.
pos-label is displaying data from the triple
This triple is then replaced in the store by
pos-label needs to rerender with the new value
The text was updated successfully, but these errors were encountered: