Only update components when their props actually change
This commit is contained in:
parent
75cd492988
commit
b72e654ff0
|
@ -3,10 +3,11 @@
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import * as ComponentLibrary from "@budibase/standard-components"
|
import * as ComponentLibrary from "@budibase/standard-components"
|
||||||
import Router from "./Router.svelte"
|
import Router from "./Router.svelte"
|
||||||
import { enrichProps } from "../utils/componentProps"
|
import { enrichProps, propsAreSame } from "../utils/componentProps"
|
||||||
import { bindingStore, builderStore } from "../store"
|
import { bindingStore, builderStore } from "../store"
|
||||||
|
|
||||||
export let definition = {}
|
export let definition = {}
|
||||||
|
let componentProps = {}
|
||||||
|
|
||||||
// Get contexts
|
// Get contexts
|
||||||
const dataContext = getContext("data")
|
const dataContext = getContext("data")
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
$: children = definition._children
|
$: children = definition._children
|
||||||
$: id = definition._id
|
$: id = definition._id
|
||||||
$: enrichedProps = enrichProps(definition, $dataContext, $bindingStore)
|
$: enrichedProps = enrichProps(definition, $dataContext, $bindingStore)
|
||||||
|
$: updateProps(enrichedProps)
|
||||||
$: styles = definition._styles
|
$: styles = definition._styles
|
||||||
|
|
||||||
// Allow component selection in the builder preview if we're previewing a
|
// Allow component selection in the builder preview if we're previewing a
|
||||||
|
@ -31,6 +33,17 @@
|
||||||
// Update component context
|
// Update component context
|
||||||
$: componentStore.set({ id, styles: { ...styles, id, allowSelection } })
|
$: 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
|
// Gets the component constructor for the specified component
|
||||||
const getComponentConstructor = component => {
|
const getComponentConstructor = component => {
|
||||||
const split = component?.split("/")
|
const split = component?.split("/")
|
||||||
|
@ -51,7 +64,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if constructor}
|
{#if constructor}
|
||||||
<svelte:component this={constructor} {...enrichedProps}>
|
<svelte:component this={constructor} {...componentProps}>
|
||||||
{#if children && children.length}
|
{#if children && children.length}
|
||||||
{#each children as child (getChildKey(child._id))}
|
{#each children as child (getChildKey(child._id))}
|
||||||
<svelte:self definition={child} />
|
<svelte:self definition={child} />
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
import { enrichDataBindings } from "./enrichDataBinding"
|
import { enrichDataBindings } from "./enrichDataBinding"
|
||||||
import { enrichButtonActions } from "./buttonActions"
|
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.
|
* Enriches component props.
|
||||||
* Data bindings are enriched, and button actions are enriched.
|
* Data bindings are enriched, and button actions are enriched.
|
||||||
|
|
Loading…
Reference in New Issue