Skip to content

Commit 37d2dcf

Browse files
committed
fix: isolate (corrected getSnapshotBeforeUpdate emulation) fixes #8.
1 parent fdcf3d6 commit 37d2dcf

File tree

1 file changed

+53
-21
lines changed

1 file changed

+53
-21
lines changed

src/index.tsx

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ import NumberFlowLite, {
99
} from "number-flow/lite"
1010
import {
1111
type Accessor,
12+
createComputed,
1213
createContext,
1314
createEffect,
1415
createMemo,
1516
createSignal,
1617
type FlowProps,
18+
on,
1719
onCleanup,
1820
onMount,
1921
splitProps,
@@ -72,11 +74,14 @@ function NumberFlowImpl(props: VoidProps<NumberFlowImplProps>) {
7274
const updateProperties = (prevProps?: NumberFlowImplProps_NoSignals) => {
7375
if (!el) return
7476

75-
// el.batched = !props.isolate (Not sure why but this breaks the animations, so isolate might not work right now. I personally think it has a very niche usecase though).
77+
el.batched = !props.isolate
7678
if (props.transformTiming)
77-
el.transformTiming ?? NumberFlowElement.defaultProps["transformTiming"]
78-
if (props.spinTiming) el.spinTiming ?? NumberFlowElement.defaultProps["spinTiming"]
79-
if (props.opacityTiming) el.opacityTiming ?? NumberFlowElement.defaultProps["opacityTiming"]
79+
el.transformTiming =
80+
props.transformTiming ?? NumberFlowElement.defaultProps["transformTiming"]
81+
if (props.spinTiming)
82+
el.spinTiming = props.spinTiming ?? NumberFlowElement.defaultProps["spinTiming"]
83+
if (props.opacityTiming)
84+
el.opacityTiming = props.opacityTiming ?? NumberFlowElement.defaultProps["opacityTiming"]
8085
if (props.animated != null) el.animated = props.animated
8186
if (props.respectMotionPreference != null)
8287
el.respectMotionPreference = props.respectMotionPreference
@@ -107,32 +112,59 @@ function NumberFlowImpl(props: VoidProps<NumberFlowImplProps>) {
107112
}
108113
})
109114

110-
// Equivalent of getSnapshotBeforeUpdate
111-
// @ts-expect-error
115+
// Update non-data properties when they change
116+
// @ts-expect-error - using return value for prev props tracking
112117
createEffect((prevProps?: NumberFlowImplProps_NoSignals) => {
113118
updateProperties(prevProps)
114-
115-
// eslint-disable-next-line solid/reactivity
116-
if (prevProps?.data !== props.data()) {
117-
if (props.group()) {
118-
props.group()!.willUpdate()
119-
props.group()!.didUpdate()
120-
return
121-
}
122-
if (!props.isolate) {
123-
el?.willUpdate()
124-
el?.didUpdate()
125-
return
126-
}
127-
}
128-
129119
return {
130120
...props,
131121
group: props.group(),
132122
data: props.data(),
133123
}
134124
})
135125

126+
// Track whether we've mounted (to skip initial render)
127+
let mounted = false
128+
onMount(() => {
129+
mounted = true
130+
})
131+
132+
// Equivalent of getSnapshotBeforeUpdate: call willUpdate() BEFORE DOM changes
133+
// createComputed runs synchronously during the reactive update phase, before effects/rendering
134+
createComputed(
135+
on(
136+
() => props.data(),
137+
(current, prev) => {
138+
// Skip initial render, only run on updates after mount
139+
if (!mounted || !el || current === prev) return
140+
141+
if (props.group()) {
142+
props.group()!.willUpdate()
143+
} else if (!props.isolate) {
144+
el.willUpdate()
145+
}
146+
}
147+
)
148+
)
149+
150+
// Equivalent of componentDidUpdate: call didUpdate() AFTER DOM changes
151+
// createEffect runs after DOM updates
152+
createEffect(
153+
on(
154+
() => props.data(),
155+
(current, prev) => {
156+
// Skip initial render, only run on updates after mount
157+
if (!mounted || !el || current === prev) return
158+
159+
if (props.group()) {
160+
props.group()!.didUpdate()
161+
} else if (!props.isolate) {
162+
el.didUpdate()
163+
}
164+
}
165+
)
166+
)
167+
136168
/**
137169
* It's exactly like a signal setter, but we're setting two things:
138170
* - innerRef (from props)

0 commit comments

Comments
 (0)