Skip to content

Commit

Permalink
feat: Toast support useToast (#1388)
Browse files Browse the repository at this point in the history
  • Loading branch information
1uokun committed Oct 28, 2024
1 parent 0d57f94 commit 72eca16
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 7 deletions.
2 changes: 1 addition & 1 deletion components/modal/useModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import prompt from '../prompt'
const StaticMethod = { alert, prompt, operation }
export type HookAPI = typeof StaticMethod & { remove: (key: number) => void }

let nextKey = 20000
let nextKey = 200000

function useModal(): readonly [
instance: HookAPI,
Expand Down
8 changes: 2 additions & 6 deletions components/toast/ToastContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React, { useEffect, useMemo } from 'react'
import {
ActivityIndicator,
Animated,
Dimensions,
Text,
View,
ViewStyle,
Expand Down Expand Up @@ -125,19 +124,16 @@ const ToastContainer: FC<ToastProps> = (p) => {
}, [icon, styles.centering, styles.image, type])

const positionStyle: ViewStyle = useMemo(() => {
const { height } = Dimensions.get('window')
const offset = height * 0.2

switch (position) {
case 'top':
return {
justifyContent: 'flex-start',
marginTop: offset,
marginTop: '20%',
}
case 'bottom':
return {
justifyContent: 'flex-end',
marginBottom: offset,
marginBottom: '20%',
}
default:
return {
Expand Down
28 changes: 28 additions & 0 deletions components/toast/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,34 @@ Toast.config({ duration: 1, position: 'top' })
Toast.getConfig()
```

### Toast.useToast()

New in `5.2.4`. antd-mobile-rn will inserted into the root node of `<Provider>` through `Portal.add` when call toast methods. Whose context is different with origin code located context.
<br/>
When you need context info (like **Modal** context), you can use `toast.useToast` to get `toastApi` instance and `contextHolder` node. And put it in your children:

```jsx
import { Modal } from 'react-native'
import { Toast } from '@ant-design/react-native'

const [toastApi, contextHolder] = Toast.useToast();

const showLoading = () => {
toastApi.loading(
// ...
);
}

return (
<Modal>
{contextHolder}
<View>
...
</View>
</Modal>
);
```

### InputStyle interface

```typescript
Expand Down
2 changes: 2 additions & 0 deletions components/toast/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
remove,
removeAll,
} from './methods'
import useToast from './useToast'

export type { ToastProps, ToastShowProps } from './PropsType'

Expand All @@ -24,6 +25,7 @@ const Toast = {
loading: methods.loading,
remove,
removeAll,
useToast,
}

export default Toast
28 changes: 28 additions & 0 deletions components/toast/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,34 @@ Toast.config({ duration: 1, position: 'top' })
Toast.getConfig()
```

### Toast.useToast()

`5.2.4`新增。直接调用 Toast 方法,antd-mobile-rn 会通过 `Portal.add` 插入到 `<Provider>` 根节点下。其 context 与当前代码所在 context 并不相同,因而无法获取 context 信息。
<br/>
当你需要 context 信息(例如 Modal 配置的内容)时,可以通过 `toast.useToast` 方法会返回 `toastApi` 实体以及 `contextHolder` 节点。将其插入到你需要获取 context 位置即可:

```jsx
import { Modal } from 'react-native'
import { Toast } from '@ant-design/react-native'

const [toastApi, contextHolder] = Toast.useToast();

const showLoading = () => {
toastApi.loading(
// ...
);
}

return (
<Modal>
{contextHolder}
<View>
...
</View>
</Modal>
);
```

### ToastStyle 语义化样式

```typescript
Expand Down
130 changes: 130 additions & 0 deletions components/toast/useToast/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import React, { useCallback, useMemo } from 'react'
import Toast, { ToastShowProps } from '..'
import { defaultConfig } from '../methods'
import ToastContainer from '../ToastContainer'

export type HookAPI = Omit<
typeof Toast,
'useToast' | 'SHORT' | 'LONG' | 'defaultConfig' | 'getConfig' | 'config'
>
let nextKey = 300000

function useToast(): readonly [
instance: HookAPI,
contextHolder?: React.ReactElement,
] {
// ========================== Effect ==========================
const [actionQueue, setActionQueue] = React.useState<
{
key: number
el: React.ReactElement
}[]
>([])

const remove = useCallback((key: number) => {
setActionQueue((prev) => prev.filter((p) => p.key !== key))
}, [])
const removeAll = useCallback(() => {
setActionQueue([])
}, [])

const ElementsHolder = React.useMemo(
() =>
actionQueue.length ? <>{actionQueue.map((a) => a.el)}</> : undefined,
[actionQueue],
)

const notice = useCallback(
(
content: string | ToastShowProps,
type: string,
duration = defaultConfig.duration,
onClose = defaultConfig.onClose,
mask = defaultConfig.mask,
) => {
let props = {
...defaultConfig,
content: content as string | React.ReactNode,
type,
duration,
onClose,
mask,
}

if (typeof content !== 'string') {
props = {
...props,
...content,
}
}

if (!props.stackable) {
removeAll()
}

const key = nextKey++
setActionQueue((prev) => [
...prev,
{
key,
el: (
<ToastContainer
{...props}
onAnimationEnd={() => {
remove(key)
}}
key={key}
/>
),
},
])
return key
},
[remove, removeAll],
)

const base = useCallback(
(type: string) => {
return (
props: string | ToastShowProps,
duration?: number,
onClose?: () => void,
mask?: boolean,
) => notice(props, type, duration, onClose, mask)
},
[notice],
)

const show = useCallback(
(props: string | ToastShowProps, duration?: number, mask?: boolean) => {
return notice(props, 'info', duration ?? 1.5, () => {}, mask ?? false)
},
[notice],
)

const methods = useMemo(
() => ({
show,
info: base('info'),
success: base('success'),
fail: base('fail'),
offline: base('offline'),
loading: base('loading'),
}),
[base, show],
)

// =========================== Hook ===========================
const fns = React.useMemo<HookAPI>(
() => ({
...methods,
remove,
removeAll,
}),
[methods, remove, removeAll],
)

return [fns, ElementsHolder] as const
}

export default useToast

0 comments on commit 72eca16

Please sign in to comment.