Only update components when their props actually change
This commit is contained in:
parent
3d77c1f38f
commit
ce6d89bc5c
|
@ -3,10 +3,11 @@
|
|||
import { writable } from "svelte/store"
|
||||
import * as ComponentLibrary from "@budibase/standard-components"
|
||||
import Router from "./Router.svelte"
|
||||
import { enrichProps } from "../utils/componentProps"
|
||||
import { enrichProps, propsAreSame } from "../utils/componentProps"
|
||||
import { bindingStore, builderStore } from "../store"
|
||||
|
||||
export let definition = {}
|
||||
let componentProps = {}
|
||||
|
||||
// Get contexts
|
||||
const dataContext = getContext("data")
|
||||
|
@ -21,6 +22,7 @@
|
|||
$: children = definition._children
|
||||
$: id = definition._id
|
||||
$: enrichedProps = enrichProps(definition, $dataContext, $bindingStore)
|
||||
$: updateProps(enrichedProps)
|
||||
$: styles = definition._styles
|
||||
|
||||
// Allow component selection in the builder preview if we're previewing a
|
||||
|
@ -31,6 +33,17 @@
|
|||
// Update component context
|
||||
$: componentStore.set({ id, styles: { ...styles, id, allowSelection } })
|
||||
|
||||
// Updates the component props.
|
||||
// Most props are deeply compared so that svelte will only trigger reactive
|
||||
// statements on props that have actually changed.
|
||||
const updateProps = props => {
|
||||
Object.keys(props).forEach(key => {
|
||||
if (!propsAreSame(props[key], componentProps[key])) {
|
||||
componentProps[key] = props[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Gets the component constructor for the specified component
|
||||
const getComponentConstructor = component => {
|
||||
const split = component?.split("/")
|
||||
|
@ -51,7 +64,7 @@
|
|||
</script>
|
||||
|
||||
{#if constructor}
|
||||
<svelte:component this={constructor} {...enrichedProps}>
|
||||
<svelte:component this={constructor} {...componentProps}>
|
||||
{#if children && children.length}
|
||||
{#each children as child (getChildKey(child._id))}
|
||||
<svelte:self definition={child} />
|
||||
|
|
|
@ -1,6 +1,22 @@
|
|||
import { enrichDataBindings } from "./enrichDataBinding"
|
||||
import { enrichButtonActions } from "./buttonActions"
|
||||
|
||||
/**
|
||||
* Deeply compares 2 props using JSON.stringify.
|
||||
* Does not consider functions, as currently only button actions have a function
|
||||
* prop and it's cheaper to just always re-render buttons than it is to deeply
|
||||
* compare them.
|
||||
*/
|
||||
export const propsAreSame = (a, b) => {
|
||||
if (a === b) {
|
||||
return true
|
||||
}
|
||||
if (typeof a === "function" || typeof b === "function") {
|
||||
return false
|
||||
}
|
||||
return JSON.stringify(a) === JSON.stringify(b)
|
||||
}
|
||||
|
||||
/**
|
||||
* Enriches component props.
|
||||
* Data bindings are enriched, and button actions are enriched.
|
||||
|
|
Loading…
Reference in New Issue