Skip to content

Commit

Permalink
fix: useSyncState logic (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ authored Jun 17, 2024
1 parent 77db279 commit 50cbe39
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 41 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"dependencies": {
"@babel/runtime": "^7.11.1",
"classnames": "^2.2.1",
"rc-util": "^5.39.3"
"rc-util": "^5.43.0"
},
"devDependencies": {
"@rc-component/father-plugin": "^1.0.1",
Expand Down
88 changes: 48 additions & 40 deletions src/hooks/useStatus.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEvent } from 'rc-util';
import useState from 'rc-util/lib/hooks/useState';
import useSyncState from 'rc-util/lib/hooks/useSyncState';
import * as React from 'react';
import { useEffect, useRef } from 'react';
import type { CSSMotionProps } from '../CSSMotion';
Expand Down Expand Up @@ -51,9 +52,11 @@ export default function useStatus(
): [MotionStatus, StepStatus, React.CSSProperties, boolean] {
// Used for outer render usage to avoid `visible: false & status: none` to render nothing
const [asyncVisible, setAsyncVisible] = useState<boolean>();
const [status, setStatus] = useState<MotionStatus>(STATUS_NONE);
const [getStatus, setStatus] = useSyncState<MotionStatus>(STATUS_NONE);
const [style, setStyle] = useState<React.CSSProperties | undefined>(null);

const currentStatus = getStatus();

const mountedRef = useRef(false);
const deadlineRef = useRef(null);

Expand All @@ -69,11 +72,12 @@ export default function useStatus(
* Clean up status & style
*/
function updateMotionEndStatus() {
setStatus(STATUS_NONE, true);
setStatus(STATUS_NONE);
setStyle(null, true);
}

const onInternalMotionEnd = useEvent((event: MotionEvent) => {
const status = getStatus();
// Do nothing since not in any transition status.
// This may happen when `motionDeadline` trigger.
if (status === STATUS_NONE) {
Expand Down Expand Up @@ -140,44 +144,48 @@ export default function useStatus(
[STEP_PREPARE]?: MotionPrepareEventHandler;
[STEP_START]?: MotionEventHandler;
[STEP_ACTIVE]?: MotionEventHandler;
}>(() => getEventHandlers(status), [status]);

const [startStep, step] = useStepQueue(status, !supportMotion, newStep => {
// Only prepare step can be skip
if (newStep === STEP_PREPARE) {
const onPrepare = eventHandlers[STEP_PREPARE];
if (!onPrepare) {
return SkipStep;
}>(() => getEventHandlers(currentStatus), [currentStatus]);

const [startStep, step] = useStepQueue(
currentStatus,
!supportMotion,
newStep => {
// Only prepare step can be skip
if (newStep === STEP_PREPARE) {
const onPrepare = eventHandlers[STEP_PREPARE];
if (!onPrepare) {
return SkipStep;
}

return onPrepare(getDomElement());
}

return onPrepare(getDomElement());
}

// Rest step is sync update
if (step in eventHandlers) {
setStyle(eventHandlers[step]?.(getDomElement(), null) || null);
}
// Rest step is sync update
if (step in eventHandlers) {
setStyle(eventHandlers[step]?.(getDomElement(), null) || null);
}

if (step === STEP_ACTIVE && status !== STATUS_NONE) {
// Patch events when motion needed
patchMotionEvents(getDomElement());

if (motionDeadline > 0) {
clearTimeout(deadlineRef.current);
deadlineRef.current = setTimeout(() => {
onInternalMotionEnd({
deadline: true,
} as MotionEvent);
}, motionDeadline);
if (step === STEP_ACTIVE && currentStatus !== STATUS_NONE) {
// Patch events when motion needed
patchMotionEvents(getDomElement());

if (motionDeadline > 0) {
clearTimeout(deadlineRef.current);
deadlineRef.current = setTimeout(() => {
onInternalMotionEnd({
deadline: true,
} as MotionEvent);
}, motionDeadline);
}
}
}

if (step === STEP_PREPARED) {
updateMotionEndStatus();
}
if (step === STEP_PREPARED) {
updateMotionEndStatus();
}

return DoStep;
});
return DoStep;
},
);

const active = isActive(step);
activeRef.current = active;
Expand Down Expand Up @@ -231,11 +239,11 @@ export default function useStatus(
useEffect(() => {
if (
// Cancel appear
(status === STATUS_APPEAR && !motionAppear) ||
(currentStatus === STATUS_APPEAR && !motionAppear) ||
// Cancel enter
(status === STATUS_ENTER && !motionEnter) ||
(currentStatus === STATUS_ENTER && !motionEnter) ||
// Cancel leave
(status === STATUS_LEAVE && !motionLeave)
(currentStatus === STATUS_LEAVE && !motionLeave)
) {
setStatus(STATUS_NONE);
}
Expand All @@ -257,14 +265,14 @@ export default function useStatus(
firstMountChangeRef.current = true;
}

if (asyncVisible !== undefined && status === STATUS_NONE) {
if (asyncVisible !== undefined && currentStatus === STATUS_NONE) {
// Skip first render is invisible since it's nothing changed
if (firstMountChangeRef.current || asyncVisible) {
onVisibleChanged?.(asyncVisible);
}
firstMountChangeRef.current = true;
}
}, [asyncVisible, status]);
}, [asyncVisible, currentStatus]);

// ============================ Styles ============================
let mergedStyle = style;
Expand All @@ -275,5 +283,5 @@ export default function useStatus(
};
}

return [status, step, mergedStyle, asyncVisible ?? visible];
return [currentStatus, step, mergedStyle, asyncVisible ?? visible];
}

0 comments on commit 50cbe39

Please sign in to comment.