Skip to content

Commit 4dd7ad1

Browse files
authored
refactor: make ref stable (#62)
* refactor: make ref stable * chore: useMemo instead
1 parent 538b35f commit 4dd7ad1

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

src/CSSMotion.tsx

+22-5
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,13 @@ export function genCSSMotion(config: CSSMotionConfig) {
147147
return getDOM(nodeRef.current) as HTMLElement;
148148
}
149149

150-
const [status, statusStep, statusStyle, mergedVisible] = useStatus(
150+
const [getStatus, statusStep, statusStyle, mergedVisible] = useStatus(
151151
supportMotion,
152152
visible,
153153
getDomElement,
154154
props,
155155
);
156+
const status = getStatus();
156157

157158
// Record whether content has rendered
158159
// Will return null for un-rendered even when `removeOnLeave={false}`
@@ -162,10 +163,26 @@ export function genCSSMotion(config: CSSMotionConfig) {
162163
}
163164

164165
// ====================== Refs ======================
165-
React.useImperativeHandle(ref, () => ({
166-
nativeElement: getDomElement(),
167-
inMotion: () => status !== STATUS_NONE,
168-
}));
166+
const refObj = React.useMemo<CSSMotionRef>(() => {
167+
const obj = {} as CSSMotionRef;
168+
Object.defineProperties(obj, {
169+
nativeElement: {
170+
enumerable: true,
171+
get: getDomElement,
172+
},
173+
inMotion: {
174+
enumerable: true,
175+
get: () => {
176+
return () => getStatus() !== STATUS_NONE;
177+
},
178+
},
179+
});
180+
return obj;
181+
}, []);
182+
183+
// We lock `deps` here since function return object
184+
// will repeat trigger ref from `refConfig` -> `null` -> `refConfig`
185+
React.useImperativeHandle(ref, () => refObj, []);
169186

170187
// ===================== Render =====================
171188
let motionChildren: React.ReactNode;

src/hooks/useStatus.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export default function useStatus(
4949
onLeaveEnd,
5050
onVisibleChanged,
5151
}: CSSMotionProps,
52-
): [MotionStatus, StepStatus, React.CSSProperties, boolean] {
52+
): [() => MotionStatus, StepStatus, React.CSSProperties, boolean] {
5353
// Used for outer render usage to avoid `visible: false & status: none` to render nothing
5454
const [asyncVisible, setAsyncVisible] = useState<boolean>();
5555
const [getStatus, setStatus] = useSyncState<MotionStatus>(STATUS_NONE);
@@ -294,5 +294,5 @@ export default function useStatus(
294294
};
295295
}
296296

297-
return [currentStatus, step, mergedStyle, asyncVisible ?? visible];
297+
return [getStatus, step, mergedStyle, asyncVisible ?? visible];
298298
}

0 commit comments

Comments
 (0)