S
SolidJSβ€’5mo 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
JCMβ€’5mo 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
bigmistqkeβ€’5mo 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
bigmistqkeβ€’5mo 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
JCMβ€’5mo 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
bigmistqkeβ€’5mo 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
JCMβ€’5mo ago
Thanks
QWu4xYV
QWu4xYVβ€’5mo 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
bigmistqkeβ€’5mo 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
QWu4xYVβ€’5mo 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
More Posts
Make sure your app is wrapped in a <Router />Hey folks, probably something silly but why can't I access `useNavigator` in my RouteGuard? AttachiFailed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted...We are facing this rather flakey error when upgrading to the new Solid Start Beta 0.4. Failed to exDownload file from public/documentsHi, I want to have an A-Element, that starts a download for a .pdf-file I placed in public/documentHaving trouble implementing a stack of views because of the lifecycle of <Dynamic>For my site, I have implemented a stack of views, sort of like on iOS where you can push and pop vieUse solid as middlewareGoal: parse existing html from third party server, read all data-component attributes from HTML, loaHow to trigger createEffect when navigating to the same URL ?Hi, is it possible to trigger a createEffect that listens to location.search from the solid router'sGetting ReferenceError: React is not defined with Vitest + Solid Testing LibraryI honestly have no idea how I am receiving this error but I am despite testing using `@solidjs/testibackend solidstart or another backend.Does solidstart make sense if a third-party backend (fastapi) is used? I don't want to write backendUnderstanding the deployment of a SolidJS app (with a separate backend)I hope this doesn’t go too off topic because this is more of a general question but I am trying to uCreating custom SolidJS hook that can be used in a global scopeNeed some help understanding how to build a custom SolidJS hook that can be used both locally inside