Good practices in SolidJS

Are there any tutorials which go in depth of what are good and bad practices when building apps with SolidJS? As someone who has no prior experience with reactive libraries I sometimes have hard time understanding if what I'm doing is good or bad practice and maybe sometimes I might be reinventing the wheel or not using SolidJS as intended. So, if there are any tutorials you could recommend on how to properly use SolidJS please let me know. Or just share general recommendations, really want to learn how to use this tool properly. Thanks!
3 Replies
bigmistqke
bigmistqke10mo ago
i don't know too much about tutorials, besides the ones from the docs, but regarding best practices: it's a bit less important in solid then in react imo. In solid the naive approach is often perfectly fine. If you want to refactor it's more for ease of development then for performance reasons. There are still gotchas, like in every framework I guess. Of the top of my head: - don't read and write to the same signal in an effect: will create an endless loop. so don't do createEffect(() => setCount(count() + 1) but instead write createEffect(() => setCount(count => count + 1) - preferably don't write to signals in effects at all: derived signals (p.ex const double = () => count() * 2) or memos when the computation is expensive (const memo = createMemo(() => count() * 2)) will be more performant then createEffect(() => setDouble(count() * 2)). - using 'singletons' (a signal not inside a component, but imported/exported from a js-module) is perfectly fine when doing client side rendering, but when doing ssr it is better to import them through context as not to accidentally create shared state on the server (that can also cause potential hydration issues) - don't destructure props and understand why. Getters/setters are used in props to access signals without having to call the function:
const [signal, setSignal] = createSignal("hello");
const obj = { get signal(){ return signal() }};
createEffect(() => console.log(obj.signal));
setTimeout(setSignal("world"), 1000)
const [signal, setSignal] = createSignal("hello");
const obj = { get signal(){ return signal() }};
createEffect(() => console.log(obj.signal));
setTimeout(setSignal("world"), 1000)
will log hello and then after a second world
const [signal, setSignal] = createSignal("hello");
const obj = { get signal(){ return signal() }};
const {signal as _signal} = obj
createEffect(() => console.log(_signal));
setTimeout(setSignal("world"), 1000)
const [signal, setSignal] = createSignal("hello");
const obj = { get signal(){ return signal() }};
const {signal as _signal} = obj
createEffect(() => console.log(_signal));
setTimeout(setSignal("world"), 1000)
will only log hello since you did accessed the signal outside a reactive context. the _signal logged inside the effect was the value hello. - last rule also applies to proxies/createStore/createMutable: accessing a property === secretly calling a signal. something to be mindful off. - instead of destructuring, use mergeProps and splitProps (I like to use defaultProps too from this issue: https://github.com/solidjs/solid/issues/1526) - use control flow components like <For/>, <Index/> and <Show/> instead of .map and ternary operators so you don't create unnecessary dom-elements (in solid <div/> creates an actual dom-element, so if u would use map and update the array a lot you would create/remove a lot of dom-elements).
elite174
elite1749mo ago
I'd add one more thing (not really obvious): use untrack (or on) when calling callbacks from props for your component for instance:
const Component = (props) => {
const [value, setValue] = createSignal(1);

// this is REALLY dangerous
// because onValueChange may use other signals
// so that means that this effect will subscribe
// on that signals too!
//createEffect(()=>{
// props.onValueChange(value())
//});

// instead use this:
createEffect(on(value, currentValue => props.onValueChange(currentValue)))

// or hacky way (prev is better)
createEffect(()=>{
// subscribe
value();

untrack(() => props.onValueChange(value()))
})


return <button type="button" onClick={()=>setValue(v => v+1)}>{value()}</button>
}
const Component = (props) => {
const [value, setValue] = createSignal(1);

// this is REALLY dangerous
// because onValueChange may use other signals
// so that means that this effect will subscribe
// on that signals too!
//createEffect(()=>{
// props.onValueChange(value())
//});

// instead use this:
createEffect(on(value, currentValue => props.onValueChange(currentValue)))

// or hacky way (prev is better)
createEffect(()=>{
// subscribe
value();

untrack(() => props.onValueChange(value()))
})


return <button type="button" onClick={()=>setValue(v => v+1)}>{value()}</button>
}
elite174
elite1749mo ago
If you're a lib author keep this in mind and provide "sanitized" functions to the user (these functions use untrack inside) which may be used inside the effect. Example: https://github.com/elite174/solid-undo-redo/blob/master/src/lib/travel.ts#L218
GitHub
solid-undo-redo/src/lib/travel.ts at master · elite174/solid-undo-r...
A list-based (O(1)) implementation of undo-redo for signals! - elite174/solid-undo-redo
Want results from more Discord servers?
Add your server
More Posts
Variable initialized in `onMount` becomes `undefined````ts let positionMenu: () => void; onMount(() => { positionMenu = getPositionMenuFun({ inputElemCannot build on serverI have a server (debian bookworm) and my local PC (Arch) My site (https://github.com/someaspy/duckduSolid-Element Custom Elements ManifestIf I'm using the Solid-Element library to generate web components, is there a way to generate a [cusWhat's the SEO situation like with solid?As far as i know MPA is better for SEO but I've not been able to find any information on it. As I knCan't start the server with https enabled on StartI have a certificate and I changed the vite.config.ts to use it by adding ```ts server: { https: { Jest, TypeScript, and @solidjs/routerI set up my project with Jest & TypeScript according to https://www.solidjs.com/guides/testing#jest-Any pattern to avoid getting ts angry when using route data fields?I am using routeData returning an object with 2 fields from it. When I use a combination of <Show> aIs there some equivalent to <Portal/> that is also compatible with ssr?I want to make a persistent modal dialog, and for that i need the `<Portal/>` component from `solid-Recommended way to track the setter of a signal?Currently, my solution involves wrapping the setter with a function. Playground: https://playground.Is it possible to pass paramters a function wrapped by a createEffect/createMemo?,I have a certain function in my component which I have noticed runs multiple times since I am refer