SolidJS, DXOS and reactivity

I am trying to port an app written in React and using DXOS (https://dxos.org). I am running into problems making the UI reactive. With React, the UI was reactive out of the box for any change from DXOS. With SolidJS, it seems like I have to wrap everything in a signal or createMemo to get the UI to react to changes. This adds up to dozens of signals needed to cover all of DXOS (database, authentication, presence etc.). My setup below works for the higher level layers such as client, identity, and spaces`, but anything inside those objects, there is no reactivity. I don't want to wrap everything in signals or stores. I already have local-first state with DXOS, why can I just consume it and have the UI react to changes? https://gist.github.com/bradstedev/96a92966db7ed8702544c00959d9490d
Gist
SolidJS / DXOS reactivity issue
SolidJS / DXOS reactivity issue. GitHub Gist: instantly share code, notes, and snippets.
4 Replies
itsyoboieltr
itsyoboieltr7mo ago
are you sure you need memo? I think it should be enough to just put it in a function and call it as is () => ...
bigmistqke
bigmistqke7mo ago
what about something like
import { Client } from '@dxos/client';
import { EchoDatabase, Space } from '@dxos/client/echo';
import { Identity } from '@dxos/client/halo';
import { SystemStatus } from '@dxos/client/services';
import { JSX, createContext, createEffect, onMount } from 'solid-js';
import { createStore } from "solid-js/store";
import { types } from '../../../schema';

type ClientProviderProps = {
children: JSX.Element;
};

type ClientContextProps = {
client?: Client;
spaces?: Space[];
space?: Space;
db?: EchoDatabase;
identity?: Identity | null;
status?: SystemStatus | null;
};

export const ClientContext = createContext<ClientContextProps>();

export const ClientProvider = (props: ClientProviderProps) => {
const client = new Client();

const [api, setApi] = createStore<{
client?: Client,
spaces?: Space[],
space?: Space,
identity?: Identity,
db?: EchoDatabase,
status?: SystemStatus | null,
}>({})

onMount(async () => {
await client.initialize();
client.addTypes(types);
await client.spaces.isReady.wait();
setApi({
client,
get spaces(){
return client?.spaces?.get()
},
get space(){
return client?.spaces?.get()[0]
},
get db(){
return api.space?.isOpen ? api.space.db : undefined
},
get status(){
return client.status.get()
}
})
});

createEffect(() => {
console.log('Client', api.client);
console.log('Identity', api.identity);
console.log('Spaces', api.spaces);
console.log('Space', api.space);
console.log('DB', api.db);
console.log('status', api.status);
});

return (
<ClientContext.Provider value={api}>
{props.children}
</ClientContext.Provider>
);
};
import { Client } from '@dxos/client';
import { EchoDatabase, Space } from '@dxos/client/echo';
import { Identity } from '@dxos/client/halo';
import { SystemStatus } from '@dxos/client/services';
import { JSX, createContext, createEffect, onMount } from 'solid-js';
import { createStore } from "solid-js/store";
import { types } from '../../../schema';

type ClientProviderProps = {
children: JSX.Element;
};

type ClientContextProps = {
client?: Client;
spaces?: Space[];
space?: Space;
db?: EchoDatabase;
identity?: Identity | null;
status?: SystemStatus | null;
};

export const ClientContext = createContext<ClientContextProps>();

export const ClientProvider = (props: ClientProviderProps) => {
const client = new Client();

const [api, setApi] = createStore<{
client?: Client,
spaces?: Space[],
space?: Space,
identity?: Identity,
db?: EchoDatabase,
status?: SystemStatus | null,
}>({})

onMount(async () => {
await client.initialize();
client.addTypes(types);
await client.spaces.isReady.wait();
setApi({
client,
get spaces(){
return client?.spaces?.get()
},
get space(){
return client?.spaces?.get()[0]
},
get db(){
return api.space?.isOpen ? api.space.db : undefined
},
get status(){
return client.status.get()
}
})
});

createEffect(() => {
console.log('Client', api.client);
console.log('Identity', api.identity);
console.log('Spaces', api.spaces);
console.log('Space', api.space);
console.log('DB', api.db);
console.log('status', api.status);
});

return (
<ClientContext.Provider value={api}>
{props.children}
</ClientContext.Provider>
);
};
?
bradstewart
bradstewart6mo ago
Thanks @bigmistqke for the code example. I tried it and it looks like a really good start so far. Reactivity is better with less code. Thanks
bigmistqke
bigmistqke6mo ago
ur welcome!