Ghirigoro
Ghirigoro
SSolidJS
Created by Ghirigoro on 2/12/2025 in #support
Using Solid Signals/Stores in React
I have an app with various frontends implemented in React. I'd like to switch to SolidJS for new frontend code (and eventually convert the old ones) but it's too big a lift to do all in one go, so I was going to try adpoting Solid incrementally. There is some logic that concerns state that is shared by all the frontends so as a first step I was thinking of converting that logic to use Solid signals/stores. It seems like signals are an independent concept and implementation and could be used as a standalone state management system, but am I missing something?
2 replies
SSolidJS
Created by Ghirigoro on 4/24/2024 in #support
Mapping props to attributes
A common pattern that comes up for me is creating components that expose the html attributes of their underlying element, while merging in their own values and defaults. For example something like this (this is not expected to work - just an example):
// MyButton.tsx
type Props = {foo:string} & JSX.HTMLAttributes<HTMLButtonElement>
const defaults = { foo:"bar", class:"my-button" };
const MyButton:ParentComponent<Props>(incoming) {
// I want to merge the classes/style of the incoming props
// rather than overwrite the defaults, but how to do that safely?
// Effectively I'm asking how to write my own mergeProps function but
// But I'm not sure A) that's a good idea, B) I understand enough about
// props in SolidJS to do that without making a mess...
const merged = mergeProps(defaults, incoming);
const [local, attrs] = splitProps(merged, ["children","foo"])
return <button {...attrs}>
<div class={`button-inner ${local.foo}}`>
{props.children}
</div>
</button>
}

// App.tsx
const App() {
return <MyButton class="a-class-to-be-merged" foo="bar">Hey!</MyButton>
}
// MyButton.tsx
type Props = {foo:string} & JSX.HTMLAttributes<HTMLButtonElement>
const defaults = { foo:"bar", class:"my-button" };
const MyButton:ParentComponent<Props>(incoming) {
// I want to merge the classes/style of the incoming props
// rather than overwrite the defaults, but how to do that safely?
// Effectively I'm asking how to write my own mergeProps function but
// But I'm not sure A) that's a good idea, B) I understand enough about
// props in SolidJS to do that without making a mess...
const merged = mergeProps(defaults, incoming);
const [local, attrs] = splitProps(merged, ["children","foo"])
return <button {...attrs}>
<div class={`button-inner ${local.foo}}`>
{props.children}
</div>
</button>
}

// App.tsx
const App() {
return <MyButton class="a-class-to-be-merged" foo="bar">Hey!</MyButton>
}
So my questions are: 1. Is this is a solved problem in Solid? I'm pretty new to the framework so I don't want to reinvent the wheel if there's an established idiom/library for this. 2. I'm not exactly clear on how the reactivity of props works. They don't seem to be a signal, so are they a store or do they have their own logic? When, where and how can they be modified? Should I wrap the guts of the component in a createEffect and expose the modified props through a signal?
5 replies
SSolidJS
Created by Ghirigoro on 3/1/2024 in #support
Hydration Mismatch. Unable to find DOM nodes for hydration key
I'm trying to setup a SolidJS SSR project with Vite, Fastify, and the @fastify/vite plugin. I've finally got something rendering, but am getting this error:
Uncaught Error: Hydration Mismatch. Unable to find DOM nodes for hydration key: 0-0
at getNextElement (chunk-TJVPM3FD.js?v=ff79f117:398:13)
at _$$component.location (App.tsx:8:2)
at @solid-refresh:25:42
at untrack (chunk-2MQNFOLP.js?v=ff79f117:574:12)
at HMRComp.createMemo.name [as fn] (@solid-refresh:25:28)
at runComputation (chunk-2MQNFOLP.js?v=ff79f117:889:22)
at updateComputation (chunk-2MQNFOLP.js?v=ff79f117:872:3)
at createMemo (chunk-2MQNFOLP.js?v=ff79f117:330:5)
at [solid-refresh]App (@solid-refresh:22:20)
at chunk-2MQNFOLP.js?v=ff79f117:702:14
Uncaught Error: Hydration Mismatch. Unable to find DOM nodes for hydration key: 0-0
at getNextElement (chunk-TJVPM3FD.js?v=ff79f117:398:13)
at _$$component.location (App.tsx:8:2)
at @solid-refresh:25:42
at untrack (chunk-2MQNFOLP.js?v=ff79f117:574:12)
at HMRComp.createMemo.name [as fn] (@solid-refresh:25:28)
at runComputation (chunk-2MQNFOLP.js?v=ff79f117:889:22)
at updateComputation (chunk-2MQNFOLP.js?v=ff79f117:872:3)
at createMemo (chunk-2MQNFOLP.js?v=ff79f117:330:5)
at [solid-refresh]App (@solid-refresh:22:20)
at chunk-2MQNFOLP.js?v=ff79f117:702:14
The App component this is happening in is as basic as you can get:
import type { Component } from "solid-js";

export function createApp() {
return <App />;
}

export const App: Component = () => {
return <div>Hello World!! </div>;
};
import type { Component } from "solid-js";

export function createApp() {
return <App />;
}

export const App: Component = () => {
return <div>Hello World!! </div>;
};
So basic in fact I'm not sure what there is to mismatch. I know it's not much info to go on but any leads on how to debug this would be appreciated. P.S. - Even with the error the app renders properly on first render. Subsequent hot updates though are received by the browser but don't change what's rendered.
6 replies
SSolidJS
Created by Ghirigoro on 2/24/2024 in #support
Create signal from store element
I have a component that takes signal as a prop:
const NumberInput:Component<{value:Signal<number>}> = props => {
// Stuff...
return <input>{some fancy business}</input>
}
const NumberInput:Component<{value:Signal<number>}> = props => {
// Stuff...
return <input>{some fancy business}</input>
}
Elsewhere I have a store that contains an array of numbers: const [store, setStore] = createStore([1,2,3]); My understanding is that SolidJS creates a signal for properties of stores. Is there a way to access that underlying signal so I can pass it to the input? I.e. <NumberInput value={store[0]/>
18 replies
SSolidJS
Created by Ghirigoro on 2/24/2024 in #support
How to react to length of store array?
I have a store representing an array:
const [pools, setPools] = createStore<Pool[]>([])
const [pools, setPools] = createStore<Pool[]>([])
Elsewhere I render a list based on that array:
<Column class="px-2">
<Row>
<For each={pools}>{(p, i) => <PoolView index={i()} />}</For>
<CreatePoolViewButton index={pools.length} />
</Row>
</Column>
<Column class="px-2">
<Row>
<For each={pools}>{(p, i) => <PoolView index={i()} />}</For>
<CreatePoolViewButton index={pools.length} />
</Row>
</Column>
pools.length is always 0, even when I successfully add an element to the pool store. How do I get the value reactively?
16 replies
SSolidJS
Created by Ghirigoro on 2/15/2024 in #support
Uninitialized signal in JSX but initialized in component
I have a component that is using an xstate machine to handle some state. At the top of the component I initialize the machine and set up a signal to handle the state, and then reference it in the JSX I return. The signal is initialized and works fine in the component body but is undefined in the JSX:
export const Authentication: Component = () => {
const fsm = createActor(machine);
const [getState, setState] = createSignal<State>(fsm.getSnapshot());

// Works fine here...
console.log("State", getState());

fsm.subscribe((state) => {setState(state);});

onMount(() => {fsm.start();});
onCleanup(() => {fsm.stop();});

// Fails in the Match component at runtime with the error:
// Uncaught ReferenceError: getState is not defined
return (
<Page>
<Switch>
<Match when={getState().matches("Checking local storage")}>
<Heading>Checking local storage...</Heading>
</Match>
</Switch>
</Page>
);
}
export const Authentication: Component = () => {
const fsm = createActor(machine);
const [getState, setState] = createSignal<State>(fsm.getSnapshot());

// Works fine here...
console.log("State", getState());

fsm.subscribe((state) => {setState(state);});

onMount(() => {fsm.start();});
onCleanup(() => {fsm.stop();});

// Fails in the Match component at runtime with the error:
// Uncaught ReferenceError: getState is not defined
return (
<Page>
<Switch>
<Match when={getState().matches("Checking local storage")}>
<Heading>Checking local storage...</Heading>
</Match>
</Switch>
</Page>
);
}
I'm new to Solid so I may be missing something about how components work, but the block at the top should execute before the return statement right? Is Solid doing some compiler magic that I'm not aware of? Dumb mistake elsewhere that I'm too undercaffeinated to see? P.S. - This is being built with Vite and the Solid plugin. P.P.S. - This seems to only happen with Match or Show. If I use one of my own components I can access getState just fine (e.g. <Heading>{getState().value}</Heading> works fine)
7 replies
SSolidJS
Created by Ghirigoro on 4/26/2023 in #support
Is there a way to untrack store reads?
The title says it all... I can see how to untrack signal reads but can't find similar functionality for store properties. Am I misunderstanding how stores work? Not reading the docs properly?
3 replies
SSolidJS
Created by Ghirigoro on 4/24/2023 in #support
Solid JS to mixins or HOCs
I've got a situation where I'd like to create a component that modifies a specific type of child component. In React I would do this using a 'render props' function or a HOC. Is there an equivalent in SolidJS?
7 replies