MCPcopy Create free account
hub / github.com/formkit/formkit / hydrate

Function hydrate

packages/core/src/node.ts:2005–2064  ·  view source on GitHub ↗

* Hydrate node and its children * * @param node - A FormKitNode | FormKitNode * @param context - A FormKitContext | FormKitContext * * @returns A FormKitNode | FormKitNode * * @internal

(node: FormKitNode, context: FormKitContext)

Source from the content-addressed store, hash-verified

2003 * @internal
2004 */
2005function hydrate(node: FormKitNode, context: FormKitContext): FormKitNode {
2006 const _value = context._value as KeyedValue
2007 // For "synced" lists the underlying nodes need to be synced to their values
2008 // before hydration.
2009 if (node.type === 'list' && node.sync) syncListNodes(node, context)
2010 // Frameworks can briefly mount a same-name replacement before unmounting the
2011 // old node. In that overlap, the children remain the source of truth.
2012 const duplicateNames = new Set<PropertyKey>()
2013 if (node.type !== 'list') {
2014 const childNames = new Set<PropertyKey>()
2015 context.children.forEach((child) => {
2016 if (childNames.has(child.name)) duplicateNames.add(child.name)
2017 childNames.add(child.name)
2018 })
2019 }
2020 context.children.forEach((child) => {
2021 if (typeof _value !== 'object') return
2022 if (duplicateNames.has(child.name) && !child.props.mergeStrategy) {
2023 partial(context, { name: child.name, value: child.value })
2024 return
2025 }
2026 if (child.name in _value) {
2027 // In this case, the parent has a value to give to the child, so we
2028 // perform a down-tree synchronous input which will cascade values down
2029 // and then ultimately back up.
2030 const childValue =
2031 child.type !== 'input' ||
2032 (_value[child.name] && typeof _value[child.name] === 'object')
2033 ? init(_value[child.name])
2034 : _value[child.name]
2035 // If the two are already equal or the child is currently disturbed then
2036 // don’t send the value down since it will squash the child’s value.
2037 if (
2038 !child.isSettled ||
2039 ((!isObject(childValue) || child.props.mergeStrategy) &&
2040 eq(childValue, child._value))
2041 )
2042 return
2043
2044 // If there is a change to the child, push the new value down.
2045 child.input(childValue, false)
2046 } else {
2047 if (node.type !== 'list' || typeof child.name === 'number') {
2048 // In this case, the parent’s values have no knowledge of the child
2049 // value — this typically occurs on the commit at the end of addChild()
2050 // we need to create a value reservation for this node’s name. This is
2051 // especially important when dealing with lists where index matters.
2052 partial(context, { name: child.name, value: child.value })
2053 }
2054 if (!_value.__init) {
2055 // In this case, someone has explicitly set the value to an empty object
2056 // with node.input({}) so we do not define the __init property:
2057 if (child.type === 'group') child.input({}, false)
2058 else if (child.type === 'list') child.input([], false)
2059 else child.input(undefined, false)
2060 }
2061 }
2062 })

Callers

nothing calls this directly

Calls 5

initFunction · 0.90
isObjectFunction · 0.90
eqFunction · 0.90
syncListNodesFunction · 0.85
partialFunction · 0.85

Tested by

no test coverage detected