The Svelte official tutorial employs such complex object in its document for <svelte:self>
let root = [
{
type: 'folder',
name: 'Important work stuff',
files: [
{ type: 'file', name: 'quarterly-results.xlsx' }
]
},
{
type: 'folder',
name: 'Animal GIFs',
files: [
{
type: 'folder',
name: 'Dogs',
files: [
{ type: 'file', name: 'treadmill.gif' },
{ type: 'file', name: 'rope-jumping.gif' }
]
},
{
type: 'folder',
name: 'Goats',
files: [
{ type: 'file', name: 'parkour.gif' },
{ type: 'file', name: 'rampage.gif' }
]
},
{ type: 'file', name: 'cat-roomba.gif' },
{ type: 'file', name: 'duck-shuffle.gif' },
{ type: 'file', name: 'monkey-on-a-pig.gif' }
]
},
{ type: 'file', name: 'TODO.md' }
];
If this object needs to be reactive and placed inside a store, how should it be done? Should the tree be wrapped as a single store, or each file and folder is its own store and stores are nested accordingly?
In both cases, it seems whenever the top-level properties are changed (svelte store considers update from objects always fresh), the whole tree will be checked for change?
A few things to know...
The
$
prefix notations for stores also works to assign a new value to a writable store:This also works to write to a single prop of an object, or individual items in an array:
From a parent component, you can bind a variable to a prop of a child component:
Child.svelte
App.svelte
Note: bindings only works when it's the same variable. That is, you can't put the bound variable in an intermediate variable, and have Svelte keep tracking this binding. Svelte does keep tracking individual props of objects (as long as they're referenced from the originally bound variable -- with dot notation), and items of arrays though, notably in
{#each}
loops:And so, knowing all this, if you put your source data in a writable store and you are precise with your 2-way bindings, you can end up with a pretty cheap solution to your question... (See in REPL)
stores.js
App.svelte
Folder.svelte
File.svelte
Note, however, that this might not be the most efficient solution.
The reason is that any change to any part of the store will be detected as a change to the whole store, and so Svelte will have to propagate and re-validate the change to every consumers (components) or this data. We're not necessarily talking about some heavy processing, because Svelte still knows the data graph and will short-circuit most of the propagation very early with very cheap and chirurgically targeted
if
tests. But still, the complexity of the processing will grow linearly (albeit slowly) with the size of the object in the store.In some cases where the data can be very big or something (maybe allow for lazy fetching of the nested nodes?), you may want to elaborate around the techniques demonstrated in the above examples. For example, you could cap the algorithmic complexity (cost) of processing a change by wrapping the recursive nodes in your data (i.e. the
files
prop in the above example) each in a writable store. Yes, that would be stores in stores (high order stores?). This would surely be a little delicate to wire together, but that would theoretically give you near infinite scalability, because every change will only propagate to the siblings of the impacted node, instead of the whole tree.