mirror of
https://github.com/streamich/react-use.git
synced 2026-01-18 14:06:52 +00:00
Merge pull request #867 from bebbi/feat/before-unload-callback
feat(useBeforeUnload): allow passing a dirty function (#842)
This commit is contained in:
commit
5ea486edf1
@ -5,6 +5,8 @@ React side-effect hook that shows browser alert when user try to reload or close
|
||||
|
||||
## Usage
|
||||
|
||||
### Boolean check
|
||||
|
||||
```jsx
|
||||
import {useBeforeUnload} from 'react-use';
|
||||
|
||||
@ -20,3 +22,28 @@ const Demo = () => {
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Function check
|
||||
|
||||
Note: Since every `dirtyFn` change registers a new callback, you should use
|
||||
[refs](https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback)
|
||||
if your test value changes often.
|
||||
|
||||
```jsx
|
||||
import {useBeforeUnload} from 'react-use';
|
||||
|
||||
const Demo = () => {
|
||||
const [dirty, toggleDirty] = useToggle(false);
|
||||
const dirtyFn = useCallback(() => {
|
||||
return dirty;
|
||||
}, [dirty]);
|
||||
useBeforeUnload(dirtyFn, 'You have unsaved changes, are you sure?');
|
||||
|
||||
return (
|
||||
<div>
|
||||
{dirty && <p>Try to reload or close tab</p>}
|
||||
<button onClick={() => toggleDirty()}>{dirty ? 'Disable' : 'Enable'}</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
const useBeforeUnload = (enabled: boolean = true, message?: string) => {
|
||||
useEffect(() => {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
const useBeforeUnload = (enabled: boolean | (() => boolean) = true, message?: string) => {
|
||||
const handler = useCallback(
|
||||
(event: BeforeUnloadEvent) => {
|
||||
const finalEnabled = typeof enabled === 'function' ? enabled() : true;
|
||||
|
||||
if (!finalEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const handler = (event: BeforeUnloadEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (message) {
|
||||
@ -14,12 +16,19 @@ const useBeforeUnload = (enabled: boolean = true, message?: string) => {
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
},
|
||||
[enabled, message]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('beforeunload', handler);
|
||||
|
||||
return () => window.removeEventListener('beforeunload', handler);
|
||||
}, [message, enabled]);
|
||||
}, [enabled, handler]);
|
||||
};
|
||||
|
||||
export default useBeforeUnload;
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useBeforeUnload, useToggle } from '../src';
|
||||
import ShowDocs from './util/ShowDocs';
|
||||
|
||||
const Demo = () => {
|
||||
const DemoBool = () => {
|
||||
const [dirty, toggleDirty] = useToggle(false);
|
||||
useBeforeUnload(dirty, 'You have unsaved changes, are you sure?');
|
||||
|
||||
@ -15,6 +15,22 @@ const Demo = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const DemoFunc = () => {
|
||||
const [dirty, toggleDirty] = useToggle(false);
|
||||
const dirtyFn = useCallback(() => {
|
||||
return dirty;
|
||||
}, [dirty]);
|
||||
useBeforeUnload(dirtyFn, 'You have unsaved changes, are you sure?');
|
||||
|
||||
return (
|
||||
<div>
|
||||
{dirty && <p>Try to reload or close tab</p>}
|
||||
<button onClick={() => toggleDirty()}>{dirty ? 'Disable' : 'Enable'}</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf('Side effects|useBeforeUnload', module)
|
||||
.add('Docs', () => <ShowDocs md={require('../docs/useBeforeUnload.md')} />)
|
||||
.add('Demo', () => <Demo />);
|
||||
.add('Demo (boolean)', () => <DemoBool />)
|
||||
.add('Demo (function)', () => <DemoFunc />);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user