diff --git a/doc/reference/reactivity.md b/doc/reference/reactivity.md index 48b24b45..75701a1d 100644 --- a/doc/reference/reactivity.md +++ b/doc/reference/reactivity.md @@ -26,9 +26,9 @@ To solve this issue, Owl provides two reactivity primitives: Most of the time, the `useState` hook is the best solution. Since version 2.0, Owl applies the fine grained reactivity at the component -level: props are automatically turned into reactive object, so Owl can track -which part of these props are consumed by each component, and is therefore able -to only rerender the impacted components. +level: reactive objects received as props are automatically subscribed to by the +component, so Owl can track which part of these props are consumed by each +component, and is therefore able to only rerender the impacted components. ## `useState` diff --git a/src/app/template_helpers.ts b/src/app/template_helpers.ts index 4e35fcdb..65fe750d 100644 --- a/src/app/template_helpers.ts +++ b/src/app/template_helpers.ts @@ -2,7 +2,6 @@ import { BDom, multi, text, toggler, createCatcher } from "../blockdom"; import { validateProps } from "../component/props_validation"; import { Markup } from "../utils"; import { html } from "../blockdom/index"; -import { TARGET } from "../reactivity"; /** * This file contains utility functions that will be injected in each template, @@ -23,7 +22,7 @@ function callSlot( defaultContent?: (ctx: any, node: any, key: string) => BDom ): BDom { key = key + "__slot_" + name; - const slots = ctx.props[TARGET].slots || {}; + const slots = ctx.props.slots || {}; const { __render, __ctx, __scope } = slots[name] || {}; const slotScope = Object.create(__ctx || {}); if (__scope) { diff --git a/src/component/component_node.ts b/src/component/component_node.ts index b990d7e9..db613462 100644 --- a/src/component/component_node.ts +++ b/src/component/component_node.ts @@ -6,6 +6,7 @@ import { NonReactive, Reactive, reactive, + toRaw, TARGET, } from "../reactivity"; import { batched, Callback } from "../utils"; @@ -62,14 +63,16 @@ type Props = { [key: string]: any }; function arePropsDifferent(props1: Props, props2: Props): boolean { for (let k in props1) { - if (props1[k] !== props2[k]) { + const prop1 = props1[k] && typeof props1[k] === "object" ? toRaw(props1[k]) : props1[k]; + const prop2 = props2[k] && typeof props2[k] === "object" ? toRaw(props2[k]) : props2[k]; + if (prop1 !== prop2) { return true; } } return Object.keys(props1).length !== Object.keys(props2).length; } -export function component
( +export function component
( name: string | ComponentConstructor
, props: P, key: string, @@ -92,7 +95,7 @@ export function component
( if (shouldRender) { node.forceNextRender = false; } else { - const currentProps = node.component.props[TARGET]; + const currentProps = node.component.props; shouldRender = parentFiber.deep || arePropsDifferent(currentProps, props); } if (shouldRender) { @@ -125,7 +128,7 @@ export function component
( type LifecycleHook = Function; -export class ComponentNode
implements VNode implements VNode implements VNode