Fix reactive store derivation overriding actions

This commit is contained in:
Andrew Kingston 2021-02-10 19:42:56 +00:00
parent 544f94954c
commit eac9dc7269
2 changed files with 22 additions and 21 deletions

View File

@ -11,17 +11,13 @@
// Clone and create new data context for this component tree // Clone and create new data context for this component tree
const context = getContext("context") const context = getContext("context")
const component = getContext("component") const component = getContext("component")
const newContext = createContextStore() const newContext = createContextStore(context)
setContext("context", newContext) setContext("context", newContext)
let initiated = false
$: providerKey = key || $component.id $: providerKey = key || $component.id
// Add data context // Add data context
$: { $: newContext.actions.provideData(providerKey, data)
newContext.actions.provideData(providerKey, $context, data)
initiated = true
}
// Instance ID is unique to each instance of a provider // Instance ID is unique to each instance of a provider
let instanceId let instanceId
@ -56,6 +52,4 @@
}) })
</script> </script>
{#if initiated} <slot />
<slot />
{/if}

View File

@ -1,20 +1,27 @@
import { writable } from "svelte/store" import { writable, derived } from "svelte/store"
export const createContextStore = () => { export const createContextStore = oldContext => {
const store = writable({}) const newContext = writable({})
const contexts = oldContext ? [oldContext, newContext] : [newContext]
const totalContext = derived(contexts, $contexts => {
return $contexts.reduce((total, context) => ({ ...total, ...context }), {})
})
// Adds a data context layer to the tree // Adds a data context layer to the tree
const provideData = (providerId, context, data) => { const provideData = (providerId, data) => {
let newData = { ...context } if (!providerId || data === undefined) {
if (providerId && data !== undefined) { return
newData[providerId] = data }
newContext.update(state => {
state[providerId] = data
// Keep track of the closest component ID so we can later hydrate a "data" prop. // Keep track of the closest component ID so we can later hydrate a "data" prop.
// This is only required for legacy bindings that used "data" rather than a // This is only required for legacy bindings that used "data" rather than a
// component ID. // component ID.
newData.closestComponentId = providerId state.closestComponentId = providerId
}
store.set(newData) return state
})
} }
// Adds an action context layer to the tree // Adds an action context layer to the tree
@ -22,14 +29,14 @@ export const createContextStore = () => {
if (!providerId || !actionType) { if (!providerId || !actionType) {
return return
} }
store.update(state => { newContext.update(state => {
state[`${providerId}_${actionType}`] = callback state[`${providerId}_${actionType}`] = callback
return state return state
}) })
} }
return { return {
subscribe: store.subscribe, subscribe: totalContext.subscribe,
actions: { provideData, provideAction }, actions: { provideData, provideAction },
} }
} }