Fix issue with multiple enrichments before components mount without affecting other components

This commit is contained in:
Andrew Kingston 2022-01-25 11:22:26 +00:00
parent bca6f34959
commit 542dc6db2f
1 changed files with 43 additions and 44 deletions

View File

@ -118,9 +118,6 @@
// Build up the final settings object to be passed to the component // Build up the final settings object to be passed to the component
$: cacheSettings(enrichedSettings, nestedSettings, conditionalSettings) $: cacheSettings(enrichedSettings, nestedSettings, conditionalSettings)
// Render key is used to determine when components need to fully remount
$: renderKey = getRenderKey(id, editing)
// Update component context // Update component context
$: componentStore.set({ $: componentStore.set({
id, id,
@ -276,8 +273,7 @@
// reactive statements as much as possible. // reactive statements as much as possible.
const cacheSettings = (enriched, nested, conditional) => { const cacheSettings = (enriched, nested, conditional) => {
const allSettings = { ...enriched, ...nested, ...conditional } const allSettings = { ...enriched, ...nested, ...conditional }
const mounted = ref?.$$set != null if (!cachedSettings) {
if (!cachedSettings || !mounted) {
cachedSettings = { ...allSettings } cachedSettings = { ...allSettings }
initialSettings = cachedSettings initialSettings = cachedSettings
} else { } else {
@ -290,24 +286,28 @@
// setting it on initialSettings directly, we avoid a double render. // setting it on initialSettings directly, we avoid a double render.
cachedSettings[key] = allSettings[key] cachedSettings[key] = allSettings[key]
if (ref?.$$set) {
// Programmatically set the prop to avoid svelte reactive statements // Programmatically set the prop to avoid svelte reactive statements
// firing inside components. This circumvents the problems caused by // firing inside components. This circumvents the problems caused by
// spreading a props object. // spreading a props object.
ref.$$set({ [key]: allSettings[key] }) ref.$$set({ [key]: allSettings[key] })
} else {
// Sometimes enrichment can occur multiple times before the
// component has mounted and been assigned a ref.
// In these cases, for some reason we need to update the
// initial settings object, even though it is equivalent by
// reference to cached settings. This solves the problem of multiple
// initial enrichments, while also not causing wasted renders for
// any components not affected by this issue.
initialSettings[key] = allSettings[key]
}
} }
}) })
} }
} }
// Generates a key used to determine when components need to fully remount.
// Currently only toggling editing requires remounting.
const getRenderKey = (id, editing) => {
return Helpers.hashString(`${id}-${editing}`)
}
</script> </script>
{#key renderKey} {#if constructor && initialSettings && (visible || inSelectedPath)}
{#if constructor && initialSettings && (visible || inSelectedPath)}
<!-- The ID is used as a class because getElementsByClassName is O(1) --> <!-- The ID is used as a class because getElementsByClassName is O(1) -->
<!-- and the performance matters for the selection indicators --> <!-- and the performance matters for the selection indicators -->
<div <div
@ -333,8 +333,7 @@
{/if} {/if}
</svelte:component> </svelte:component>
</div> </div>
{/if} {/if}
{/key}
<style> <style>
.component { .component {