Leal
Leal
SSolidJS
Created by Leal on 1/7/2025 in #support
Complex createResource management
I'm trying to write a way to handle a specific scenario where I wanted to use something like a const ws = useWebSocket(); that: - when called on the server side, initializes a WebSocket connection to another server and returns a server side wrapper to the WebSocket ~ must be waited and cached - when called on the client side, initializes a WebSocket connection to the SolidStart server and returns a client side wrapper to the WebSocket ~ must be cached - when the user session id changes, the connection must be closed if the id becomes undefined or create a new one if the id is not the same as the previous one - the wrapper contains the same functions on the server side and client side, allowing it to be used inside other resources By cached I mean using the same resource in more than a single component does not create a second connection. I know there's a package named solid-cached-resource that solves this exact problem using resources The ideal approach would be something exactly like an createResource, wich can receive a signal to refetch, stores the current fetch state (loading, error or loaded) and has a deferStream option that makes the server await until the fetch is completed but I couldn't make it work using resources due to: - the resource result is transferred to the client side for hydration, therefore the client WebSocket is not initialized - the server side data must not be transferred to the client I'm not sure if SolidStart provides a way to do this operation or if I should study the createResource source code to create something alike that allows this scenario. Any help is appreciated!
14 replies
SSolidJS
Created by Leal on 1/5/2025 in #support
Unable to provide context to children
I'm writing a dropdown component, so I decided to use a context to provide tools to the children. I have defined the context as an object with some setters and accessors to a set of signals and no matter what I do, I can't get it from the children components. I'm using SolidJS + SolidStart Here's some code snippets:
type DropdownCtx = {
rootElement: Accessor<HTMLDivElement>;
setValue: Setter<any>;
setSelected: Setter<HTMLElement | undefined>;
};

const DropdownContext = createContext<DropdownCtx>();

export const DropdownComponent = <T extends any>(props: DropdownProps<T>) => {
let rootElement!: HTMLDivElement;
const rootElementAccessor = () => rootElement;

const children = solidChildren(() => props.children); // I import solid's children fn as solidChildren

const [value, setValue] = createSignal(props.value);
const [selected, setSelected] = createSignal<HTMLElement | undefined>(undefined);

// ...

const context: DropdownCtx = {
rootElement: rootElementAccessor,
setValue,
setSelected,
};

// ...

return (
// ...
<dialog
class='dropdown__popup'
id={idPopup()}
open={isOpen()}
>
<DropdownContext.Provider value={context}>
{children()}
</DropdownContext.Provider>
</dialog>
);
};


export const DropdownItemComponent = <T extends any>(props: DropdownItemProps<T>) => {
// ...

const context = useContext(DropdownContext);

if (!context) {
throw new Error("Missing context");
}

// ...
};

// Usage

<DropdownComponent>
<DropdownItemComponent>
<span>help :(</span>
</DropdownItemComponent>
</DropdownComponent>
type DropdownCtx = {
rootElement: Accessor<HTMLDivElement>;
setValue: Setter<any>;
setSelected: Setter<HTMLElement | undefined>;
};

const DropdownContext = createContext<DropdownCtx>();

export const DropdownComponent = <T extends any>(props: DropdownProps<T>) => {
let rootElement!: HTMLDivElement;
const rootElementAccessor = () => rootElement;

const children = solidChildren(() => props.children); // I import solid's children fn as solidChildren

const [value, setValue] = createSignal(props.value);
const [selected, setSelected] = createSignal<HTMLElement | undefined>(undefined);

// ...

const context: DropdownCtx = {
rootElement: rootElementAccessor,
setValue,
setSelected,
};

// ...

return (
// ...
<dialog
class='dropdown__popup'
id={idPopup()}
open={isOpen()}
>
<DropdownContext.Provider value={context}>
{children()}
</DropdownContext.Provider>
</dialog>
);
};


export const DropdownItemComponent = <T extends any>(props: DropdownItemProps<T>) => {
// ...

const context = useContext(DropdownContext);

if (!context) {
throw new Error("Missing context");
}

// ...
};

// Usage

<DropdownComponent>
<DropdownItemComponent>
<span>help :(</span>
</DropdownItemComponent>
</DropdownComponent>
I have tried: - Using props.children instead of children() - Moving the context provider up - Declaring the context as a store using createStore I can't get Solid to provide the context and I don't really know the reason, every try throws the error :(
13 replies