S
SolidJS10mo ago
QWu4xYV

Understanding memoization re-running

Hi everyone, I'm new to SolidJS (from React), but so far enjoying it! I was running into some unexpected behavior when dealing with memoization though, and I was wondering if someone could help me understand, or help me figure out if I had run into a bug (either in my code or in Solid). Solid Playground link: https://playground.solidjs.com/anonymous/2850a930-a45f-48d6-92ff-fc644cee0bbc Notice that if you click the "Add item" button below "SimpleMemo" multiple times, only a single item appears (unexpected), while if you click the other two, items continue to appear (expected). In the SimpleMemo case, I have a simple memoization function which uses a Map to memoize a function based on a single input arg. The function passed in is calling Solid's createMemo, so I have two layers of memoization. The outer "simpleMemo" is designed to memoize based on input arg, while the inner createMemo is designed to memoize based on Solid's reactive primitives. SimpleMemoInitialCall illustrates that if I call the memoization function once anywhere outside the JSX, it works fine. NonMemo illustrates that if I don't do the "simpleMemo"-izing, it also works fine. Can someone help me figure out why this is happening? Thank you!!
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
9 Replies
JCM
JCM10mo ago
I found this example quite hard to read. You seem to make a memo from the store and put that store in a value cache stored in a Map. This part is a bit convoluted and hard to follow. I made a simplified example here: https://playground.solidjs.com/anonymous/0c909400-ca65-445a-8d96-d396e519072c That being said, I don't really know why the memo stops being run after the 2nd update. General comments could be made, but it might be a bit off topic to the question. It's not good practice to make a memo out of the root object of the store, since you pay the price of the store (eg. proxy overhead), but loose the fine grained reactivity of the store (eg. if anything of the store changes, everything dependent on any part of the store will update). I recommend to use the store directly. If the initial idea of this structure were some performance considerations, it's likely doing the opposite of the intended.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke10mo ago
yes, this pattern to create lazy memos won't work. if you want your memos to be lazy I would recommend using solid-primitive's createLazyMemo 👉 https://primitives.solidjs.community/package/memo#createlazymemo
Solid Primitives
A library of high-quality primitives that extend SolidJS reactivity
bigmistqke
bigmistqke10mo ago
and indeed, bit hard to understand your original code sample @QWu4xYV maybe it would be helpful to understand what you are trying to accomplish exactly
JCM
JCM10mo ago
@bigmistqke do you have a simple explanation of why it doesn't work? To me it doesn't look like a lazy memo (in the sense of lazy evaluation), but just delayed creation until the first use. Does it matter if it's stored in a global variable or a local variable in a component?
bigmistqke
bigmistqke10mo ago
To me it doesn't look like a lazy memo
you are correct
do you have a simple explanation of why it doesn't work?
it has something to do with owners, but I am unsure about the details explanation from fabio 👉 https://discord.com/channels/722131463138705510/861229287868858379/1201936564343799889
JCM
JCM10mo ago
Thanks
QWu4xYV
QWu4xYVOP10mo ago
Thank you both! Ownership is the main concept I was missing, and now that I understand it, it totally makes sense why my code wasn't working. @bigmistqke , I know you posted in the #docs channel about this; just wanted to agree/add that I do think having a section on how ownership works in the Guides section would be helpful. Once I knew that's what I was missing, I was able to find the documentation under getOwner/runWithOwner, but I expected that I could learn all the key concepts to understand the API docs from the Guides, rather than inferring concepts from the API docs. I do see some mention in the "SolidJS: Reactivity to Rendering" link, in the Reactivity section of the Guides, but an explicit section (or maybe subsection under a new "Advanced" heading) inside Reactivity would be great. To be clear, I think overall the docs are great and I appreciate everyone who has worked on them (thank you!), just wanted to offer the feedback 🙂 As for why my code was structured in a convoluted way, the main intent was to use the outer simpleMemo to maintain consistent object references based on the input args, and the inner createMemo to memoize expensive computation done on the list (which in my use case can get very long). There's almost certainly a better way to structure it; I just ran into this while throwing together a solution and it revealed that there's something I didn't understand about Solid, so I wanted to ask primarily for the sake of understanding.
bigmistqke
bigmistqke10mo ago
Ye I agree that it would be good if this was explained a bit more, especially because it is the base of how the auto-cleanup of effects (and also onCleanup) works. I do think it is 99% an anti-pattern to actually make use of getOwner/runWithOwner and there are probably better primitives/patterns to make use of. Have you seen mapArray / indexArray ? They are the primitives used underneath <For/> and <Index/>
const [signal, setSignal] = createSignal([]);
const memoArray = createMemo(
mapArray(signal, (value, index) => ...expensive calculation...)
)
const [signal, setSignal] = createSignal([]);
const memoArray = createMemo(
mapArray(signal, (value, index) => ...expensive calculation...)
)
in the above example the expensive calculation is only executed once per value.
const [signal, setSignal] = createSignal([]);
const memoArray = createMemo(
indexArray(signal, (value, index) => ...expensive calculation...)
)
const [signal, setSignal] = createSignal([]);
const memoArray = createMemo(
indexArray(signal, (value, index) => ...expensive calculation...)
)
and ☝️ here once per index.
QWu4xYV
QWu4xYVOP10mo ago
Makes sense, thank you! I'll rework my code a bit and if I run into any issues with finding the right patterns, I'll reach out here 🙂
Want results from more Discord servers?
Add your server