Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 30 additions & 17 deletions src/components/swipe-action/swipe-action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ export const SwipeAction = forwardRef<SwipeActionRef, SwipeActionProps>(
draggingRef.current = false
}

function open(side: SideType) {
if (side === 'right') {
api.start({ x: -getRightWidth() })
} else {
api.start({ x: getLeftWidth() })
}
p.onActionsReveal?.(side)
}

const bind = useDrag(
state => {
dragCancelRef.current = state.cancel
Expand Down Expand Up @@ -161,34 +170,32 @@ export const SwipeAction = forwardRef<SwipeActionRef, SwipeActionProps>(

useImperativeHandle(ref, () => ({
show: (side: SideType = 'right') => {
if (side === 'right') {
api.start({
x: -getRightWidth(),
})
} else if (side === 'left') {
api.start({
x: getLeftWidth(),
})
}
p.onActionsReveal?.(side)
open(side)
},
close,
}))

useEffect(() => {
if (!props.closeOnTouchOutside) return
function handle(e: Event) {
if (x.get() === 0) {
return
const root = rootRef.current
if (!root) return
function onTouchOutside(e: Event) {
if (x.get() === 0) return
if (!root.contains(e.target as Node)) {
close()
}
const root = rootRef.current
if (root && !root.contains(e.target as Node)) {
}
function onFocusOutside(e: FocusEvent) {
if (x.get() === 0) return
if (!root.contains(e.relatedTarget as Node)) {
close()
}
}
document.addEventListener('touchstart', handle)
document.addEventListener('touchstart', onTouchOutside)
root.addEventListener('focusout', onFocusOutside)
return () => {
document.removeEventListener('touchstart', handle)
document.removeEventListener('touchstart', onTouchOutside)
root.removeEventListener('focusout', onFocusOutside)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}, [props.closeOnTouchOutside])
Comment on lines 178 to 200
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

useEffect 钩子在依赖数组中缺少 props.onClose。由于事件监听器调用了 close(),而 close() 内部使用了 props.onClose,如果 onClose 发生变化,监听器可能会捕获到旧的回调版本。此外,建议在监听器中使用 x.goal 代替 x.get()x.goal 代表动画的目标值,这可以避免在动画过程中触发冗余的调用,使逻辑更加健壮。

    useEffect(() => {
      if (!props.closeOnTouchOutside) return
      const root = rootRef.current
      if (!root) return
      function onTouchOutside(e: Event) {
        if (x.goal === 0) return
        if (!root.contains(e.target as Node)) {
          close()
        }
      }
      function onFocusOutside(e: FocusEvent) {
        if (x.goal === 0) return
        if (!root.contains(e.relatedTarget as Node)) {
          close()
        }
      }
      document.addEventListener('touchstart', onTouchOutside)
      root.addEventListener('focusout', onFocusOutside)
      return () => {
        document.removeEventListener('touchstart', onTouchOutside)
        root.removeEventListener('focusout', onFocusOutside)
      }
    }, [props.closeOnTouchOutside, props.onClose])


Expand Down Expand Up @@ -233,6 +240,9 @@ export const SwipeAction = forwardRef<SwipeActionRef, SwipeActionProps>(
<div
className={`${classPrefix}-actions ${classPrefix}-actions-left`}
ref={leftRef}
onFocus={() => {
if (x.get() !== getLeftWidth()) open('left')
}}
Comment on lines +243 to +245
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

建议使用 x.goal 代替 x.get() 来判断组件是否已经处于打开或正在打开的状态。这可以避免在动画执行过程中重复触发 open 调用以及 onActionsReveal 回调。

Suggested change
onFocus={() => {
if (x.get() !== getLeftWidth()) open('left')
}}
onFocus={() => {
if (x.goal !== getLeftWidth()) open('left')
}}

>
{props.leftActions.map(renderAction)}
</div>
Expand Down Expand Up @@ -262,6 +272,9 @@ export const SwipeAction = forwardRef<SwipeActionRef, SwipeActionProps>(
<div
className={`${classPrefix}-actions ${classPrefix}-actions-right`}
ref={rightRef}
onFocus={() => {
if (x.get() !== -getRightWidth()) open('right')
}}
Comment on lines +275 to +277
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

建议使用 x.goal 代替 x.get()。这可以确保一致性,并避免在同一个操作容器内的元素之间移动焦点时触发不必要的动画启动。

Suggested change
onFocus={() => {
if (x.get() !== -getRightWidth()) open('right')
}}
onFocus={() => {
if (x.goal !== -getRightWidth()) open('right')
}}

>
{props.rightActions.map(renderAction)}
</div>
Expand Down
Loading