Pull To Refresh 사용자가 화면을 아래로 당겨 콘텐츠를 새로고침하는 컴포넌트입니다.
import "./styles" ;
import {
PullToRefreshContent,
PullToRefreshIndicator,
PullToRefreshRoot,
} from "@/components/ui/pull-to-refresh" ;
import { PARAGRAPH, useRefreshObservation } from "./use-refresh-observation" ;
export default function Example () {
const { refreshCount , lastEvent , callbacks } = useRefreshObservation ();
return (
< view className = "ptr-preview" >
< text className = "ptr-preview__title" >Pull To Refresh</ text >
< text className = "ptr-preview__hint" >
최상단에서 아래로 당겨보세요. 짧게 당기면 취소되고, 충분히 당긴 뒤 놓으면 1초 동안
새로고침합니다.
</ text >
< text className = "ptr-preview__status" >
{ `refresh 횟수: ${ refreshCount } · 마지막 이벤트: ${ lastEvent }` }
</ text >
< PullToRefreshRoot className = "ptr-preview__frame" { ... callbacks}>
< PullToRefreshIndicator />
< PullToRefreshContent >
< view className = "ptr-preview__body" >
{Array. from ({ length: 8 }, ( _ , index ) => (
< view key = {index} className = "ptr-preview__item" >
< text className = "ptr-preview__paragraph" >{ `${ index + 1 }. ${ PARAGRAPH }` }</ text >
</ view >
))}
</ view >
</ PullToRefreshContent >
</ PullToRefreshRoot >
</ view >
);
}
npx @seed-design/cli@latest add ui:pull-to-refresh pnpm dlx @seed-design/cli@latest add ui:pull-to-refresh yarn dlx @seed-design/cli@latest add ui:pull-to-refresh bun x @seed-design/cli@latest add ui:pull-to-refresh
의존성 설치
npm install @seed-design/lynx-react yarn add @seed-design/lynx-react pnpm add @seed-design/lynx-react bun add @seed-design/lynx-react 아래 코드를 복사 후 붙여넣고 사용하세요 /**
* @file ui:pull-to-refresh
* @requires @seed-design/lynx-react@^1.0.0
* @requires @seed-design/lynx-css@^1.0.0
**/
import { forwardRef, type ComponentRef } from "@lynx-js/react" ;
import { PullToRefresh } from "@seed-design/lynx-react" ;
import { ProgressCircle } from "./progress-circle" ;
export interface PullToRefreshRootProps extends PullToRefresh . RootProps {}
export const PullToRefreshRoot = PullToRefresh.Root;
export interface PullToRefreshIndicatorProps
extends Omit < PullToRefresh . IndicatorProps , "children" > {}
export const PullToRefreshIndicator = forwardRef <
ComponentRef <typeof PullToRefresh.Indicator > ,
PullToRefreshIndicatorProps
> (( props , ref ) => (
< PullToRefresh.Indicator ref = {ref} { ... props}>
{( indicatorProps ) => < ProgressCircle size = "24" tone = "neutral" { ... indicatorProps} />}
</ PullToRefresh.Indicator >
));
PullToRefreshIndicator.displayName = "PullToRefreshIndicator" ;
export interface PullToRefreshContentProps extends PullToRefresh . ContentProps {}
export const PullToRefreshContent = PullToRefresh.Content;
/**
* This file is a snippet from SEED Design, helping you get started quickly with @seed-design/* packages.
* You can extend this snippet however you want.
*/
SEED의 최소 지원 Lynx Engine은 3.6입니다. PullToRefresh는 @lynx-js/gesture-runtime의 NativeGesture를 사용하므로 앱의 기존 React 플러그인 설정에 enableNewGesture: true를 추가하세요.
pluginReactLynx ({
engineVersion: "3.6" ,
enableNewGesture: true ,
});
enableNewGesture의 Since 2.16은 엔진 설정의 도입 기록입니다. SEED의 최소 지원 엔진을 뜻하지 않습니다. 설정 위치와 생략 조건은 Feature Flags 에서 확인하세요.
onPtrPullStart?(( context : PullToRefreshContext ) => void ) | undefined
onPtrPullMove?(( context : PullToRefreshContext ) => void ) | undefined
onPtrReady?(() => void ) | undefined
onPtrRefresh?(() => Promise <void> ) | undefined
disabled?boolean | undefined
onPtrRefresh에 새로고침 작업을 반환하는 비동기 함수를 전달하세요. threshold의 기본값은 88, displacementMultiplier의 기본값은 0.75입니다. 당긴 변위가 threshold를 넘은 상태에서 놓으면 새로고침을 시작합니다. Promise가 완료되거나 실패하면 콘텐츠가 원래 위치로 돌아옵니다.
고유 prop이 없습니다.
Content는 세로 <scroll-view>입니다. Root에 높이를 지정하고 화면의 세로 스크롤은 Content 하나로 구성하세요. 중첩된 세로 스크롤 컨테이너는 당김 제스처와 경합할 수 있습니다.
가로로 넘길 수 있는 Tabs Carousel의 Tab 1에만 PullToRefresh를 배치합니다. Tab 2에서는 새로고침하지 않습니다.
import "./styles" ;
import {
PullToRefreshContent,
PullToRefreshIndicator,
PullToRefreshRoot,
} from "@/components/ui/pull-to-refresh" ;
import { TabsCarousel, TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs" ;
import { PARAGRAPH, useRefreshObservation } from "./use-refresh-observation" ;
export default function Example () {
const { refreshCount , lastEvent , callbacks } = useRefreshObservation ();
return (
< view className = "ptr-preview" >
< text className = "ptr-preview__title" >Pull To Refresh</ text >
< text className = "ptr-preview__status" >
{ `Tab 1 refresh 횟수: ${ refreshCount } · 마지막 이벤트: ${ lastEvent }` }
</ text >
< TabsRoot
defaultValue = "1"
contentLayout = "fill"
className = "ptr-preview__tabs"
style = {{ width: "100%" }}
>
< TabsList >
< TabsTrigger value = "1" >Tab 1</ TabsTrigger >
< TabsTrigger value = "2" >Tab 2</ TabsTrigger >
</ TabsList >
< TabsCarousel swipeable className = "ptr-preview__carousel" >
< TabsContent value = "1" className = "ptr-preview__tab" >
< PullToRefreshRoot className = "ptr-preview__frame" { ... callbacks}>
< PullToRefreshIndicator />
< PullToRefreshContent >
< view className = "ptr-preview__body" >
< text className = "ptr-preview__paragraph" >{ PARAGRAPH }</ text >
</ view >
</ PullToRefreshContent >
</ PullToRefreshRoot >
</ TabsContent >
< TabsContent value = "2" className = "ptr-preview__tab" >
< view className = "ptr-preview__body" >
< text className = "ptr-preview__paragraph" >PTR is not available in this tab.</ text >
</ view >
</ TabsContent >
</ TabsCarousel >
</ TabsRoot >
</ view >
);
}
disabled 속성으로 PTR을 비활성화할 수 있습니다. 당기는 도중 비활성화하면 당김이 취소됩니다. 이미 시작한 새로고침은 반환한 Promise가 끝날 때까지 유지됩니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import {
PullToRefreshContent,
PullToRefreshIndicator,
PullToRefreshRoot,
} from "@/components/ui/pull-to-refresh" ;
import { Switch } from "@/components/ui/switch" ;
import { useRefreshObservation } from "./use-refresh-observation" ;
export default function Example () {
const [ disabled , setDisabled ] = useState ( false );
const { refreshCount , lastEvent , callbacks } = useRefreshObservation ();
function onCheckedChange ( checked : boolean ) {
"background only" ;
setDisabled (checked);
}
return (
< view className = "ptr-preview" >
< text className = "ptr-preview__title" >Disabled</ text >
< text className = "ptr-preview__status" >
{ `disabled: ${ JSON . stringify ( disabled ) } · refresh 횟수: ${ refreshCount } · 마지막 이벤트: ${ lastEvent }` }
</ text >
< PullToRefreshRoot className = "ptr-preview__frame" disabled = {disabled} { ... callbacks}>
< PullToRefreshIndicator />
< PullToRefreshContent >
< view className = "ptr-preview__body" >
< view className = "ptr-preview__disabled-row" >
< text className = "ptr-preview__label" >Disabled</ text >
< Switch
checked = {disabled}
onCheckedChange = {onCheckedChange}
accessibility-label = "Disabled"
/>
</ view >
</ view >
</ PullToRefreshContent >
</ PullToRefreshRoot >
</ view >
);
}
Root 안의 특정 영역에서 당김을 막으려면 usePullToRefreshPreventPull()이 반환한 props를 해당 <view>에 전달하세요. 같은 요소에 main-thread:bindtouchstart를 함께 지정하지 마세요.
import "./styles" ;
import { usePullToRefreshPreventPull } from "@seed-design/lynx-react" ;
import {
PullToRefreshContent,
PullToRefreshIndicator,
PullToRefreshRoot,
} from "@/components/ui/pull-to-refresh" ;
import { useRefreshObservation } from "./use-refresh-observation" ;
function ProtectedRegion () {
const preventPullProps = usePullToRefreshPreventPull ();
return (
< view className = "ptr-preview__protected" { ... preventPullProps}>
< text className = "ptr-preview__paragraph" >
이 영역은 당겨서 새로고침이 불가능합니다. Aliquip ad amet eu dolore id enim excepteur
laboris officia anim in. Irure irure nulla sit eiusmod aliqua sint excepteur amet laboris.
</ text >
</ view >
);
}
function PullableRegion () {
return (
< view className = "ptr-preview__item" >
< text className = "ptr-preview__paragraph" >
이 영역은 당겨서 새로고침이 가능합니다. Amet in laborum proident fugiat mollit quis aute
mollit esse nostrud. Excepteur ea proident ipsum duis. Nulla Lorem pariatur exercitation
velit anim.
</ text >
</ view >
);
}
export default function Example () {
const { refreshCount , lastEvent , callbacks } = useRefreshObservation ();
return (
< view className = "ptr-preview" >
< text className = "ptr-preview__title" >Prevent Pull</ text >
< text className = "ptr-preview__status" >
{ `refresh 횟수: ${ refreshCount } · 마지막 이벤트: ${ lastEvent }` }
</ text >
< PullToRefreshRoot className = "ptr-preview__frame" { ... callbacks}>
< PullToRefreshIndicator />
< PullToRefreshContent >
< view className = "ptr-preview__body" >
< PullableRegion />
< ProtectedRegion />
< PullableRegion />
< ProtectedRegion />
</ view >
</ PullToRefreshContent >
</ PullToRefreshRoot >
</ view >
);
}
Lynx는 Root가 배치와 clipping을 맡고 Content가 세로 스크롤을 담당합니다. asChild는 지원하지 않습니다.
Content 내부의 중첩 스크롤 영역을 자동으로 탐지하지 않습니다.
스크롤하다 최상단에 도달한 경우 손을 뗀 뒤 다시 당겨야 새로고침이 시작됩니다.