Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions .changeset/page-visibility-effect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'react-simplikit': minor
---

Add `usePageVisibilityEffect`, which runs a callback when the page visibility changes and pairs by name with `usePageVisibility`, which returns the same value as state. `useVisibilityEvent` is deprecated in favor of `usePageVisibilityEffect` and still works as before, since it is now the same function under its old name. This reverses the note from #435 that `useVisibilityEvent` is no longer deprecated. It is deprecated again because of the rename, not because it is going away: it keeps working throughout v1 and may be removed in a later major version.
2 changes: 1 addition & 1 deletion .scripts/commands/generateSkill/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Backticks in this table mark catalog entries only.
| Long press / double click | `useLongPress` / `useDoubleClick` |
| Element enters or leaves the viewport | `useIntersectionObserver` |
| How long an element stayed visible (impression tracking) | `useImpressionRef` / `ImpressionArea` |
| React to tab / page visibility changes with a callback | `useVisibilityEvent` |
| React to tab / page visibility changes with a callback | `usePageVisibilityEffect` |
| Read the current tab / page visibility as state | `usePageVisibility` |
| Device location | `useGeolocation` |
| Combine multiple refs into one | `mergeRefs` |
Expand Down
21 changes: 14 additions & 7 deletions .scripts/verifyDocsI18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ try {
)
).reduce((total, count) => total + count, 0);
const guidePageCount = 11;
const renamedPageRedirectCount = 2;
const renamedPageRedirectCount = 4;

assert.equal(
stubs.length,
Expand All @@ -161,6 +161,8 @@ try {
'ja/mobile/utils/isServer.html',
'hooks/useCallbackOncePerRender.html',
'ko/core/hooks/useCallbackOncePerRender.html',
'hooks/useVisibilityEvent.html',
'ko/core/hooks/useVisibilityEvent.html',
]) {
assert.equal(stubPaths.has(expected), true, `the legacy URL ${expected} must keep a redirect`);
}
Expand All @@ -177,12 +179,17 @@ try {
}

// A renamed export has no page of its own, so its old URLs must land on the page of its new name.
for (const from of ['hooks/useCallbackOncePerRender.html', 'ja/core/hooks/useCallbackOncePerRender.html']) {
assert.equal(
stubs.find(stub => stub.from === from)?.to,
from.replace('core/', '').replace('useCallbackOncePerRender', 'useCallbackOnce'),
`${from} must redirect to the useCallbackOnce page`
);
for (const [oldName, newName] of [
['useCallbackOncePerRender', 'useCallbackOnce'],
['useVisibilityEvent', 'usePageVisibilityEffect'],
]) {
for (const from of [`hooks/${oldName}.html`, `ja/core/hooks/${oldName}.html`]) {
assert.equal(
stubs.find(stub => stub.from === from)?.to,
from.replace('core/', '').replace(oldName, newName),
`${from} must redirect to the ${newName} page`
);
}
}

for (const { from, to } of stubs) {
Expand Down
2 changes: 2 additions & 0 deletions .vitepress/libs/legacyRedirects.mts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ const RETIRED_MOBILE_PAGES = new Set([
const RENAMED_REFERENCE_REDIRECTS: RedirectPair[] = [
{ from: 'hooks/useCallbackOncePerRender.html', to: 'hooks/useCallbackOnce.html' },
{ from: 'core/hooks/useCallbackOncePerRender.html', to: 'hooks/useCallbackOnce.html' },
{ from: 'hooks/useVisibilityEvent.html', to: 'hooks/usePageVisibilityEffect.html' },
{ from: 'core/hooks/useVisibilityEvent.html', to: 'hooks/usePageVisibilityEffect.html' },
];

export function collectLegacyRedirects(): RedirectPair[] {
Expand Down
5 changes: 3 additions & 2 deletions packages/plugin/skills/react-simplikit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Backticks in this table mark catalog entries only.
| Long press / double click | `useLongPress` / `useDoubleClick` |
| Element enters or leaves the viewport | `useIntersectionObserver` |
| How long an element stayed visible (impression tracking) | `useImpressionRef` / `ImpressionArea` |
| React to tab / page visibility changes with a callback | `useVisibilityEvent` |
| React to tab / page visibility changes with a callback | `usePageVisibilityEffect` |
| Read the current tab / page visibility as state | `usePageVisibility` |
| Device location | `useGeolocation` |
| Combine multiple refs into one | `mergeRefs` |
Expand Down Expand Up @@ -99,6 +99,7 @@ Backticks in this table mark catalog entries only.
| [`useNetworkStatus`](references/useNetworkStatus.md) | `useNetworkStatus` is a React hook that provides access to the Network Information API. |
| [`useOutsideClickEffect`](references/useOutsideClickEffect.md) | `useOutsideClickEffect` is a React hook that triggers a callback when a click event occurs outside the specified container(s). |
| [`usePageVisibility`](references/usePageVisibility.md) | `usePageVisibility` is a React hook that detects page visibility changes. |
| [`usePageVisibilityEffect`](references/usePageVisibilityEffect.md) | `usePageVisibilityEffect` is a React hook that listens to changes in the document's visibility state and triggers a callback. |
| [`usePreservedCallback`](references/usePreservedCallback.md) | `usePreservedCallback` is a React hook that maintains a stable reference to a callback function while ensuring it always has access to the latest state or props. |
| [`usePreservedReference`](references/usePreservedReference.md) | `usePreservedReference` is a React hook that helps maintain the reference of a value when it hasn't changed, while ensuring you can safely use the latest state. |
| [`usePrevious`](references/usePrevious.md) | `usePrevious` is a React hook that returns the previous value of the input state. |
Expand All @@ -112,7 +113,6 @@ Backticks in this table mark catalog entries only.
| [`useThrottledValue`](references/useThrottledValue.md) | `useThrottledValue` is a React hook that returns a throttled copy of the given value. |
| [`useTimeout`](references/useTimeout.md) | `useTimeout` is a React hook that executes a callback function after a specified delay. |
| [`useToggle`](references/useToggle.md) | `useToggle` is a React hook that simplifies managing a boolean state. |
| [`useVisibilityEvent`](references/useVisibilityEvent.md) | `useVisibilityEvent` is a React hook that listens to changes in the document's visibility state and triggers a callback. |
| [`useVisualViewport`](references/useVisualViewport.md) | `useVisualViewport` is a React hook that tracks Visual Viewport changes. |

### components
Expand Down Expand Up @@ -147,6 +147,7 @@ These still work but are kept only for backward compatibility. Do not use them i
| Name | Notice |
| --- | --- |
| `useCallbackOncePerRender` | Use `useCallbackOnce` instead. |
| `useVisibilityEvent` | Use `usePageVisibilityEffect` instead. |

## Learn more

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# useVisibilityEvent
# usePageVisibilityEffect

`useVisibilityEvent` is a React hook that listens to changes in the document's visibility state and triggers a callback.
`usePageVisibilityEffect` is a React hook that listens to changes in the document's visibility state and triggers a callback.
In v0 this hook was named `useVisibilityEvent`. The old name still works but is deprecated.

## Interface

```ts
function useVisibilityEvent(
function usePageVisibilityEffect(
callback: (visibilityState: 'visible' | 'hidden') => void,
options?: object
): void;
Expand Down Expand Up @@ -43,10 +44,10 @@ This function does not return anything.
## Example

```tsx
import { useVisibilityEvent } from 'react-simplikit';
import { usePageVisibilityEffect } from 'react-simplikit';

function Component() {
useVisibilityEvent(visibilityState => {
usePageVisibilityEffect(visibilityState => {
console.log(`Document is now ${visibilityState}`);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useEffect, useRef } from 'react';

import { useDebouncedCallback } from '../useDebouncedCallback/useDebouncedCallback.ts';
import { useIntersectionObserver } from '../useIntersectionObserver/index.ts';
import { usePageVisibilityEffect } from '../usePageVisibilityEffect/index.ts';
import { usePreservedCallback } from '../usePreservedCallback/index.ts';
import { useVisibilityEvent } from '../useVisibilityEvent/index.ts';

export type UseImpressionRefOptions = Partial<{
onImpressionStart: () => void;
Expand Down Expand Up @@ -96,7 +96,7 @@ export function useImpressionRef<Element extends HTMLElement>({
[impressionEndHandler]
);

useVisibilityEvent(documentVisible => {
usePageVisibilityEffect(documentVisible => {
if (!isIntersectingRef.current) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type PageVisibility = {
* It monitors when the user switches tabs or minimizes the browser using the Page Visibility API.
* Useful for pausing/resuming animations, videos, or background tasks to improve performance and the user experience.
*
* @see `useVisibilityEvent` runs a callback on each change instead of returning state.
* @see `usePageVisibilityEffect` runs a callback on each change instead of returning state.
*
* @returns {PageVisibility} Page visibility information
* - isVisible `boolean` - `true` if the page is currently visible to the user
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# useVisibilityEvent
# usePageVisibilityEffect

`useVisibilityEvent` es un Hook de React que escucha los cambios en el estado de visibilidad del documento y ejecuta un callback.
`usePageVisibilityEffect` es un Hook de React que escucha los cambios en el estado de visibilidad del documento y ejecuta un callback.
En v0 este Hook se llamaba `useVisibilityEvent`. El nombre anterior sigue funcionando, pero está obsoleto.

## Interfaz

```ts
function useVisibilityEvent(
function usePageVisibilityEffect(
callback: (visibilityState: 'visible' | 'hidden') => void,
options?: object
): void;
Expand Down Expand Up @@ -43,10 +44,10 @@ Esta función no devuelve ningún valor.
## Ejemplo

```tsx
import { useVisibilityEvent } from 'react-simplikit';
import { usePageVisibilityEffect } from 'react-simplikit';

function Component() {
useVisibilityEvent(visibilityState => {
usePageVisibilityEffect(visibilityState => {
console.log(`El estado del documento ahora es ${visibilityState}`);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { usePageVisibilityEffect } from './usePageVisibilityEffect.ts';
export { useVisibilityEvent } from './useVisibilityEvent.ts';
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# useVisibilityEvent
# usePageVisibilityEffect

`useVisibilityEvent` は、ドキュメントの表示状態の変化を監視し、コールバックを呼び出す React フックです。
`usePageVisibilityEffect` は、ドキュメントの表示状態の変化を監視し、コールバックを呼び出す React フックです。
v0 では、このフックは `useVisibilityEvent` という名前でした。以前の名前も引き続き動作しますが、非推奨です。

## インターフェース

```ts
function useVisibilityEvent(
function usePageVisibilityEffect(
callback: (visibilityState: 'visible' | 'hidden') => void,
options?: object
): void;
Expand Down Expand Up @@ -43,10 +44,10 @@ function useVisibilityEvent(
## 使用例

```tsx
import { useVisibilityEvent } from 'react-simplikit';
import { usePageVisibilityEffect } from 'react-simplikit';

function Component() {
useVisibilityEvent(visibilityState => {
usePageVisibilityEffect(visibilityState => {
console.log(`Document is now ${visibilityState}`);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# useVisibilityEvent
# usePageVisibilityEffect

문서의 가시성 상태 변화를 감지하고 콜백을 실행하는 리액트 훅이에요.
문서의 가시성 상태 변화를 감지하고 콜백을 실행하는 리액트 훅이에요. v0에서는 이 훅의 이름이 `useVisibilityEvent`였어요. 이전 이름도 계속 동작하지만 deprecated 상태예요.

## 인터페이스

```ts
function useVisibilityEvent(
function usePageVisibilityEffect(
callback: (visibilityState: 'visible' | 'hidden') => void,
options?: object
): void;
Expand Down Expand Up @@ -43,10 +43,10 @@ function useVisibilityEvent(
## 예시

```tsx
import { useVisibilityEvent } from 'react-simplikit';
import { usePageVisibilityEffect } from 'react-simplikit';

function Component() {
useVisibilityEvent(visibilityState => {
usePageVisibilityEffect(visibilityState => {
console.log(`Document is now ${visibilityState}`);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# useVisibilityEvent
# usePageVisibilityEffect

`useVisibilityEvent` is a React hook that listens to changes in the document's visibility state and triggers a callback.
`usePageVisibilityEffect` is a React hook that listens to changes in the document's visibility state and triggers a callback.
In v0 this hook was named `useVisibilityEvent`. The old name still works but is deprecated.

## Interface

```ts
function useVisibilityEvent(
function usePageVisibilityEffect(
callback: (visibilityState: 'visible' | 'hidden') => void,
options?: object
): void;
Expand Down Expand Up @@ -43,10 +44,10 @@ This function does not return anything.
## Example

```tsx
import { useVisibilityEvent } from 'react-simplikit';
import { usePageVisibilityEffect } from 'react-simplikit';

function Component() {
useVisibilityEvent(visibilityState => {
usePageVisibilityEffect(visibilityState => {
console.log(`Document is now ${visibilityState}`);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { describe, expect, it, vi } from 'vitest';

import { renderHookSSR } from '../../_internal/test-utils/renderHookSSR.tsx';

import { usePageVisibilityEffect } from './usePageVisibilityEffect.ts';
import { useVisibilityEvent } from './useVisibilityEvent.ts';

describe('useVisibilityEvent', () => {
describe('usePageVisibilityEffect', () => {
it('calls the callback when visibility changes', async () => {
const mockCallback = vi.fn();

await renderHookSSR(() => useVisibilityEvent(mockCallback));
await renderHookSSR(() => usePageVisibilityEffect(mockCallback));

await act(async () => simulateVisibilityChange('hidden'));

Expand All @@ -22,15 +23,15 @@ describe('useVisibilityEvent', () => {

it('is safe on server side rendering', () => {
const callback = vi.fn();
renderHookSSR.serverOnly(() => useVisibilityEvent(callback));
renderHookSSR.serverOnly(() => usePageVisibilityEffect(callback));

expect(callback).not.toHaveBeenCalled();
});

it('should not call the callback on initial render if immediate is false', async () => {
const mockCallback = vi.fn();

await renderHookSSR(() => useVisibilityEvent(mockCallback, { immediate: false }));
await renderHookSSR(() => usePageVisibilityEffect(mockCallback, { immediate: false }));

expect(mockCallback).not.toHaveBeenCalled();
});
Expand All @@ -40,22 +41,26 @@ describe('useVisibilityEvent', () => {

await act(async () => simulateVisibilityChange('visible'));

await renderHookSSR(() => useVisibilityEvent(mockCallback, { immediate: true }));
await renderHookSSR(() => usePageVisibilityEffect(mockCallback, { immediate: true }));

expect(mockCallback).toHaveBeenCalledWith('visible');
});

it('should remove the event listener on unmount', async () => {
const mockCallback = vi.fn();

const { unmount } = await renderHookSSR(() => useVisibilityEvent(mockCallback));
const { unmount } = await renderHookSSR(() => usePageVisibilityEffect(mockCallback));

unmount();

await act(async () => simulateVisibilityChange('hidden'));

expect(mockCallback).not.toHaveBeenCalled();
});

it('keeps the deprecated useVisibilityEvent as the same function', () => {
expect(useVisibilityEvent).toBe(usePageVisibilityEffect);
});
});

function simulateVisibilityChange(visibilityState: 'visible' | 'hidden') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ type Options = {

/**
* @description
* `useVisibilityEvent` is a React hook that listens to changes in the document's visibility state and triggers a callback.
* `usePageVisibilityEffect` is a React hook that listens to changes in the document's visibility state and triggers a callback.
* In v0 this hook was named `useVisibilityEvent`. The old name still works but is deprecated.
*
* @see `usePageVisibility` returns the visibility as state instead of running a callback.
*
Expand All @@ -17,18 +18,21 @@ type Options = {
* with the current visibility state.
*
* @example
* import { useVisibilityEvent } from 'react-simplikit';
* import { usePageVisibilityEffect } from 'react-simplikit';
*
* function Component() {
* useVisibilityEvent(visibilityState => {
* usePageVisibilityEffect(visibilityState => {
* console.log(`Document is now ${visibilityState}`);
* });
*
* return <p>Check the console for visibility changes.</p>;
* }
*/

export function useVisibilityEvent(callback: (visibilityState: 'visible' | 'hidden') => void, options: Options = {}) {
export function usePageVisibilityEffect(
callback: (visibilityState: 'visible' | 'hidden') => void,
options: Options = {}
) {
const handleVisibilityChange = useCallback(() => {
callback(document.visibilityState);
}, [callback]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { usePageVisibilityEffect } from './usePageVisibilityEffect.ts';

/**
* @description
* `useVisibilityEvent` is the name `usePageVisibilityEffect` had in v0.
*
* @deprecated Use `usePageVisibilityEffect` instead.
*/
export const useVisibilityEvent = usePageVisibilityEffect;
Loading
Loading