Skip to content

Commit 276a9bf

Browse files
committed
fix(useFileSubscribe): value getter ref to prevent infinite looping
BREAKING CHANGE: removed options and replaced with optional throttle
1 parent 82e98e5 commit 276a9bf

File tree

3 files changed

+16
-20
lines changed

3 files changed

+16
-20
lines changed

src/hooks/useFile.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ interface FileHook<F> {
3535
* @param throttle The timeout if unfetched memo promise.
3636
*/
3737
export function useFile<F extends FileLike>(file: F, throttle?: number): FileHook<F> {
38-
const [name, nameErr] = useFileSubscribe(file, f => f.name, 'onnamechange', { throttle });
39-
const [thumbnail, thumbnailErr] = useFileSubscribe(file, f => f.thumbnail, 'onthumbnailchange', { throttle });
40-
const [fileObj, fileObjErr] = useFileSubscribe(file, f => f.fileObj, 'onfileobjchange', { throttle });
41-
const [documentObj, documentObjErr] = useFileSubscribe(file, f => f.documentObj, 'ondocumentobjchange', { throttle });
38+
const [name, nameErr] = useFileSubscribe(file, f => f.name, 'onnamechange', throttle);
39+
const [thumbnail, thumbnailErr] = useFileSubscribe(file, f => f.thumbnail, 'onthumbnailchange', throttle);
40+
const [fileObj, fileObjErr] = useFileSubscribe(file, f => f.fileObj, 'onfileobjchange', throttle);
41+
const [documentObj, documentObjErr] = useFileSubscribe(file, f => f.documentObj, 'ondocumentobjchange', throttle);
4242

4343
const fileValue = useMemo<FileHook<F>>(
4444
() => ({

src/hooks/useFileSubscribe.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
1-
import { useEffect, useState, useMemo } from 'react';
1+
import { useEffect, useMemo, useRef, useState } from 'react';
22
import { FileEventType, FileLike, MemoizedPromise } from '../data';
33
import { DEFAULT_THROTTLE_TIMEOUT } from '../utils';
44

5-
export interface UseFileSubscribeOptions {
6-
/** The timeout to throttle initial fetch of value. Default: 500ms. */
7-
throttle?: number;
8-
}
9-
105
/**
116
* Will subscribe to a value from a file and return the value, as well as any
127
* async errors.
138
* @param file The file to subscribe to.
149
* @param getCurrentValue Function to extract the current value from the file.
1510
* @param eventType The event type to subscribe. Won't subscribe if not given.
11+
* @param throttle The timeout to throttle initial fetch of value. Default: 500ms.
1612
*/
1713
export function useFileSubscribe<F extends FileLike, T>(
1814
file: F,
1915
getCurrentValue: (file: F) => T | MemoizedPromise<T>,
2016
eventType?: FileEventType,
21-
options: UseFileSubscribeOptions = {},
17+
throttle?: number,
2218
) {
19+
const getValue = useRef(getCurrentValue);
20+
2321
const [error, setError] = useState<any>();
2422
const [value, setValue] = useState<T | undefined>(() => {
25-
const currentValue = getCurrentValue(file);
23+
const currentValue = getValue.current(file);
2624
if (currentValue instanceof MemoizedPromise) return undefined;
2725
return currentValue;
2826
});
@@ -43,19 +41,20 @@ export function useFileSubscribe<F extends FileLike, T>(
4341
const subscribe = (delay?: boolean) => {
4442
setError(undefined);
4543

46-
const val = getCurrentValue(file);
44+
const val = getValue.current(file);
4745
if (!(val instanceof MemoizedPromise)) {
4846
// Non-memoized-promise, can set directly.
4947
setValue(val);
5048
return;
5149
}
5250

53-
if (!delay || val.done || options.throttle === 0) {
51+
setValue(undefined);
52+
if (!delay || val.done || throttle === 0) {
5453
setMemoValue(val);
5554
} else {
5655
timeout = window.setTimeout(() => {
5756
setMemoValue(val);
58-
}, options.throttle ?? DEFAULT_THROTTLE_TIMEOUT);
57+
}, throttle ?? DEFAULT_THROTTLE_TIMEOUT);
5958
}
6059
};
6160

@@ -70,7 +69,7 @@ export function useFileSubscribe<F extends FileLike, T>(
7069
cancelled = true;
7170
clearTimeout(timeout);
7271
};
73-
}, [eventType, file, getCurrentValue, options.throttle]);
72+
}, [eventType, file, throttle]);
7473

7574
return useMemo(() => [value, error, setValue], [error, value]);
7675
}

src/storybook-helpers/data/files.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,7 @@ export class FakeFile implements FileLike {
3737
const internals = (() => {
3838
if (options.pending) return async () => new Promise(() => {});
3939
if (options.lazy) return async () => Promise.resolve(parameter);
40-
if (options.error)
41-
return async () => {
42-
throw new Error();
43-
};
40+
if (options.error) return () => Promise.reject('Some error.');
4441
return parameter;
4542
})();
4643
return new MemoizedPromise(internals as FuturableOrLazy<T>);

0 commit comments

Comments
 (0)