Skip to content

Commit 3465e9a

Browse files
authored
feat: optional fire on unmount (#15)
* add ability to toggle save on unmount * test changes * update docs
1 parent 23aa284 commit 3465e9a

File tree

7 files changed

+61
-19
lines changed

7 files changed

+61
-19
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.4.0] - 5-15-22
9+
10+
## Added
11+
12+
- A toggle to cancel saving on unmount `saveOnUnmount`
13+
- The ability to save falsy values
14+
- Dev page using vite to preview current build
15+
- React 18 support
16+
17+
## Changed
18+
19+
- Package builds using vite
20+
- Switched to PNPM
21+
- Test run using vitest
22+
- All dependencies bumped to latest version
23+
824
## [0.3.1] - 12-21-21
925

1026
## Added

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,16 @@ npm i react-autosave
9898
| data | TData | The controlled form value to be auto saved |
9999
| onSave | (data: TData) => any | The callback function to save your data |
100100
| interval (optional) | number | The number of milliseconds between save attempts. Defaults to 2000 |
101+
| saveOnUnmount (optional) | boolean | Defaults to true. Set to false to prevent saving on unmount |
101102

102103
### Contributing
103104

104105
Issues and PRs are more than welcome. Please clone the repo and setup your environment with:
105106

106107
```sh
107-
yarn
108+
pnpm
108109
```
109110

110-
The test suite can be run with `yarn test`
111+
The test suite can be run with `pnpm test`
112+
Buid the library with `pnpm build`
113+
A demo page can be viewed with `pnpm build && pnpm dev`

example/App.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
import React from 'react';
1+
import React, { Dispatch, SetStateAction } from 'react';
22
import { useState } from 'react';
33
import { useAutosave } from '..';
44

55
function App() {
6+
const [showForm, setShowForm] = useState(true);
67
const [text, setText] = useState('hello world');
78
const [value, setValue] = useState(text);
89

9-
useAutosave({ data: text, onSave: setValue });
10-
1110
return (
1211
<div
1312
style={{
@@ -21,18 +20,26 @@ function App() {
2120
padding: 16,
2221
}}
2322
>
24-
<input
25-
type="text"
26-
data-testid="input"
27-
value={text}
28-
onChange={(e) => setText(e.target.value)}
29-
/>
23+
{showForm ? <Form setText={setText} text={text} setValue={setValue} /> : null}
3024
<p>
3125
Save function called with:{' '}
3226
<span style={{ fontWeight: 'bold' }}>{value}</span>
3327
</p>
28+
<button onClick={() => setShowForm(prev => !prev)}>Toggle form</button>
3429
</div>
3530
);
3631
}
3732

33+
const Form = ({text, setText, setValue}: {text: string, setText: Dispatch<SetStateAction<string>>, setValue: Dispatch<SetStateAction<string>>}) => {
34+
useAutosave({ data: text, onSave: setValue });
35+
return (
36+
<input
37+
type="text"
38+
data-testid="input"
39+
value={text}
40+
onChange={(e) => setText(e.target.value)}
41+
/>
42+
);
43+
};
44+
3845
export default App;

src/Autosave.test.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import Autosave from './Autosave';
77

88
type TestProps = {
99
onSave: (data: any) => Promise<any>;
10+
saveOnUnmount?: boolean;
1011
};
11-
function TestComponent({ onSave }: TestProps) {
12+
function TestComponent({ onSave, saveOnUnmount = true }: TestProps) {
1213
const [data, setdata] = React.useState('hello world');
1314
const [showForm, setShowForm] = React.useState(true);
1415
return showForm ? (
@@ -19,7 +20,7 @@ function TestComponent({ onSave }: TestProps) {
1920
value={data}
2021
onChange={(e) => setdata(e.target.value)}
2122
/>
22-
<Autosave data={data} onSave={onSave} />
23+
<Autosave data={data} onSave={onSave} saveOnUnmount={saveOnUnmount} />
2324
<button
2425
type="button"
2526
data-testid="unmount"
@@ -90,4 +91,16 @@ describe('<Autosave />', () => {
9091
expect(saveFunction).toHaveBeenCalledTimes(1);
9192
vi.clearAllMocks();
9293
});
94+
95+
it('Can toggle off saving when unmounted', async () => {
96+
vi.useFakeTimers();
97+
const user = userEvent.setup({advanceTimers: (time) => vi.advanceTimersByTime(time)});
98+
const saveFunction = vi.fn();
99+
render(<TestComponent onSave={saveFunction} saveOnUnmount={false} />);
100+
101+
await user.click(screen.getByTestId('unmount'));
102+
103+
expect(saveFunction).toHaveBeenCalledTimes(0);
104+
vi.clearAllMocks();
105+
});
93106
});

src/Autosave.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ import { AutosaveProps } from './props';
22
import useAutosave from './useAutosave';
33

44
const Autosave = <TData, TReturn>({
5-
data,
6-
onSave,
7-
interval = 2000,
85
element = null,
6+
...props
97
}: AutosaveProps<TData, TReturn>) => {
10-
useAutosave({ data, onSave, interval });
8+
useAutosave(props);
119
return element;
1210
};
1311

src/props.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export interface CommonProps<TData, TReturn> {
55
onSave: (data: TData) => Promise<TReturn> | TReturn | void;
66
/** The number of milliseconds between save attempts. Defaults to 2000 */
77
interval?: number;
8+
/** Set to false if you do not want the save function to fire on unmount */
9+
saveOnUnmount?: boolean;
810
}
911

1012
export interface AutosaveProps<TData, TReturn>

src/useAutosave.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ function useAutosave<TData, TReturn>({
66
data,
77
onSave,
88
interval = 2000,
9+
saveOnUnmount = true
910
}: CommonProps<TData, TReturn>) {
1011
const valueOnCleanup = useRef(data);
1112
const initialRender = useRef(true);
@@ -24,8 +25,10 @@ function useAutosave<TData, TReturn>({
2425
}, [data]);
2526

2627
useEffect(() => () => {
27-
onSave(valueOnCleanup.current);
28-
}, [onSave]);
28+
if (saveOnUnmount) {
29+
onSave(valueOnCleanup.current);
30+
}
31+
}, [onSave, saveOnUnmount]);
2932
}
3033

3134
export default useAutosave;

0 commit comments

Comments
 (0)