Skip to content

Commit

Permalink
docs: modify demos
Browse files Browse the repository at this point in the history
  • Loading branch information
vikiboss committed Jun 20, 2024
1 parent 7b52c66 commit d215b4a
Show file tree
Hide file tree
Showing 14 changed files with 81 additions and 63 deletions.
12 changes: 9 additions & 3 deletions src/use-async-effect/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,18 @@ import { Source } from '@/components'
## API

```tsx
useAsyncEffect(callback, deps?)
useAsyncEffect(asyncCallback, deps)
```

### Callback
### AsyncCallback

Same as [React.useEffect](https://react.dev/reference/react/useEffect).
A effect callback, support **async** function.

```tsx
export type AsyncEffectCallback = (isCancelled: () => boolean) => void

export type UseAsyncEffectCallback = AsyncEffectCallback
```
### Deps
Expand Down
2 changes: 1 addition & 1 deletion src/use-async-effect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createAsyncEffect } from '../utils/create-effect/async'

import type { AsyncEffectCallback } from '../utils/create-effect/async'

export interface UseAsyncEffectCallback extends AsyncEffectCallback {}
export type UseAsyncEffectCallback = AsyncEffectCallback

/**
* like `React.useEffect` but it's can accept an `async` function
Expand Down
4 changes: 1 addition & 3 deletions src/use-async-fn/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ const { run, loading, value, error } = useAsyncFn(asyncFn, options)

### AsyncFn

```tsx
export type AsyncFn = (...args: any[]) => Promise<any>
```
A function that returns a promise.

### Options

Expand Down
3 changes: 2 additions & 1 deletion src/use-async-lock/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ export function App() {
const fetchData = useAsyncFn(async () => {
await mockFetch(300)
setData(OTP())
return OTP()
})

const lockedFetchData = useAsyncLock(fetchData.run, () => countActions.inc())
const lockedFetchData = useAsyncLock(fetchData.run, countActions.inc)

return (
<Card>
Expand Down
20 changes: 11 additions & 9 deletions src/use-async-lock/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,25 @@ import { Source } from '@/components'
## API

```tsx
const lockedFn = useAsyncLock(fn, onMeetLock)
const lockedFn = useAsyncLock(asyncFn, onMeetLock)
```

### Fn
### AsyncFn

```tsx
export type Fn = (...args: any[]) => Promise<any>
```
A function that returns a promise.

### OnMeetLock

```tsx
export type onMeetLock = () => void
```
A function that will be called when the function is locked and is called again.

### Returns

A function that can be used to ensure that **only one is running at a time**, return a promise that resolves the return value of the async function or the return value of the invalid operation callback function.

```tsx
export type lockedFn = (...args: T) => Promise<ReturnType<T>>
export type UseAsyncLockReturn<T extends AnyFunc, R extends AnyFunc> = (
...args: Parameters<T>
) => R extends undefined
? Promise<Awaited<ReturnType<T>> | undefined>
: Promise<Awaited<ReturnType<T>> | Awaited<ReturnType<R>>>Promise<ReturnType<T>>
```
19 changes: 12 additions & 7 deletions src/use-async-lock/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { useRef } from 'react'
import { useGetterRef } from '../use-getter-ref'
import { useLatest } from '../use-latest'
import { useStableFn } from '../use-stable-fn'

import type { AnyFunc } from '../utils/basic'

export function useAsyncLock<T extends AnyFunc>(asyncFn: T, onMeetLock?: () => void): T {
const isLockedRef = useRef(false)
export type UseAsyncLockReturn<T extends AnyFunc, R extends AnyFunc> = (
...args: Parameters<T>
) => R extends undefined
? Promise<Awaited<ReturnType<T>> | undefined>
: Promise<Awaited<ReturnType<T>> | Awaited<ReturnType<R>>>

export function useAsyncLock<T extends AnyFunc, R extends AnyFunc>(asyncFn: T, onMeetLock?: R) {
const [isLockedRef, isLocked] = useGetterRef(false)
const latest = useLatest({ asyncFn, onMeetLock })

const lockedAsync = useStableFn(async (...args: Parameters<T>) => {
const { asyncFn, onMeetLock } = latest.current

if (isLockedRef.current) {
onMeetLock?.()
return
if (isLocked()) {
return onMeetLock?.()
}

isLockedRef.current = true
Expand All @@ -25,5 +30,5 @@ export function useAsyncLock<T extends AnyFunc>(asyncFn: T, onMeetLock?: () => v
}
})

return lockedAsync as T
return lockedAsync as UseAsyncLockReturn<T, R>
}
27 changes: 8 additions & 19 deletions src/use-async-update-effect/demo.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
import { Button, Card, KeyValue, Zone } from '@/components'
import { Button, Card, KeyValue } from '@/components'
import { useAsyncUpdateEffect, useCounter, useToggle } from '@shined/react-use'

import type { SetIntervalReturn } from '../utils/basic'

export function App() {
const [show, toggle] = useToggle(true)

return (
<Card>
<Button onClick={toggle}>Toggle mount</Button>
{show && <Count />}
</Card>
)
}

function Count() {
const [status, toggle] = useToggle(false)
const [count, actions] = useCounter(0)

// biome-ignore lint/correctness/useExhaustiveDependencies: for demo
useAsyncUpdateEffect(
async (isCancelled) => {
const timer: SetIntervalReturn = window.setInterval(() => {
const timer = setInterval(() => {
// use `isCancelled()` to check if the effect is cancelled (unmount).
if (isCancelled()) return window.clearInterval(timer)
if (isCancelled()) return clearInterval(timer)
// safely do something when component is not unmount.
actions.inc(1)
}, 1000)
Expand All @@ -32,9 +19,11 @@ function Count() {
)

return (
<Zone row={false} border="amber" width="">
<Card row={false}>
<KeyValue label="Count" value={count} />
<Button onClick={toggle}>Toggle Status</Button>
</Zone>
<div>
<Button onClick={toggle}>Toggle Status</Button>
</div>
</Card>
)
}
2 changes: 1 addition & 1 deletion src/use-before-unload/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ useBeforeUnload(callback, options)
A function that will be called right before the page is potentially unloaded.

```tsx
export type Callback = (e: BeforeUnloadEvent) => void
export type UseBeforeUnloadCallback = (e: BeforeUnloadEvent) => void
```
### Options
Expand Down
5 changes: 4 additions & 1 deletion src/use-mouse-in-element/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ export function App() {
<KeyValue label="elementHeight" value={mouseInEl.elementHeight} />
<KeyValue label="elementWidth" value={mouseInEl.elementWidth} />
</Zone>
<div id="el-mouse-in-element" className="mt-2 size-120px rounded bg-red" />
<div
id="el-mouse-in-element"
className={`mt-2 size-120px rounded ${mouseInEl.isOutside ? 'bg-amber/80' : 'bg-primary/80'}`}
/>
</Card>
)
}
13 changes: 10 additions & 3 deletions src/utils/create-effect/async.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { useGetterRef } from '../../use-getter-ref'
import { useLatest } from '../../use-latest'

import type { DependencyList } from 'react'
import type { ExtendedReactEffect } from '../basic'

export type AsyncEffectCallback = (isCancelled: () => boolean) => void

export function createAsyncEffect<T = unknown>(effect: ExtendedReactEffect<T>) {
return (callback: AsyncEffectCallback, deps?: DependencyList, ...args: T[]): void => {
const [isCancelledRef, isCancelled] = useGetterRef(false)
const latest = useLatest({ callback })

effect(
() => {
let cancelled = false
callback(() => cancelled)
isCancelledRef.current = false
latest.current.callback(isCancelled)

return () => {
cancelled = true
isCancelledRef.current = true
}
},
deps,
Expand Down
4 changes: 2 additions & 2 deletions src/utils/create-effect/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function createUpdateEffect<T = unknown>(effect: ExtendedReactEffect<T>)

return (callback: () => void, deps?: DependencyList, ...args: T[]): void => {
const isActualUpdate = useRef(false)
const latestCallback = useLatest(callback)
const latest = useLatest({ callback })

effectOnce(
() => {
Expand All @@ -26,7 +26,7 @@ export function createUpdateEffect<T = unknown>(effect: ExtendedReactEffect<T>)
if (!isActualUpdate.current) {
isActualUpdate.current = true
} else {
return latestCallback.current()
return latest.current.callback()
}
},
deps,
Expand Down
4 changes: 4 additions & 0 deletions website/docs/features/ref-getter.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ console.log(isActive) // Outputs: true

It is a ref getter created by `usePausable`, see [Pausable](/docs/features/pausable) for more details.

### `isCancelled` {#is-cancelled}

It is a ref getter params in `useAsyncEffect` callback, see [useAsyncEffect](/reference/use-async-effect) for more details.

### `isMounted` {#is-mounted}

It is a ref getter created by `useMounted`, see [useMounted](/reference/use-mounted) for more details.
Expand Down
2 changes: 1 addition & 1 deletion website/src/components/doc-related/raw-code.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import CodeBlock from '@theme/CodeBlock'
import { useToggle } from '@site/../src'
import CodeBlock from '@theme/CodeBlock'
import { Button } from '../demo-related'

const ignores = ['prettier-ignore', 'biome-ignore']
Expand Down
27 changes: 15 additions & 12 deletions website/src/components/doc-related/source.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ export function Source({ name, tsx }: SourceProps) {
].map((item) => ({ ...item, url: `${url}/${item.path}` }))

return (
<div className="flex gap-2">
{list.map((item) => (
<a
key={item.name}
className="px-2 py-0 bg-primary/12 rounded text-primary/80 hover:text-primary"
href={item.url}
target="_blank"
rel="noreferrer"
>
{item.name}
</a>
))}
<div>
<p>Click links below to view source on GitHub.</p>
<div className="flex gap-4">
{list.map((item) => (
<a
key={item.name}
className="py-0 text-primary/80 hover:text-primary"
href={item.url}
target="_blank"
rel="noreferrer"
>
{item.name}
</a>
))}
</div>
</div>
)
}

0 comments on commit d215b4a

Please sign in to comment.