Skip to content

Commit 43dba60

Browse files
committed
[firestore] Make sure that all internal methods are wrapped with useCallback
1 parent 40689a8 commit 43dba60

File tree

3 files changed

+66
-96
lines changed

3 files changed

+66
-96
lines changed

firestore/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ Returns:
111111
- `snapshot`: a `firestore.QuerySnapshot`, or `undefined` if no query is supplied
112112
- `loading`: a `boolean` to indicate if the data is still being loaded
113113
- `error`: Any `firestore.FirestoreError` returned by Firebase when trying to load the data, or `undefined` if there is no error
114+
- `reload()`: a function that can be called to trigger a reload of the data
114115

115116
### useCollectionData
116117

@@ -163,6 +164,7 @@ Returns:
163164
- `loading`: a `boolean` to indicate if the data is still being loaded
164165
- `error`: Any `firestore.FirestoreError` returned by Firebase when trying to load the data, or `undefined` if there is no error
165166
- `snapshot`: a `firestore.QuerySnapshot`, or `undefined` if no query is supplied. This allows access to the underlying snapshot if needed for any reason, e.g. to view the snapshot metadata
167+
- `reload()`: a function that can be called to trigger a reload of the data
166168

167169
See [Transforming data](#transforming-data) for how to transform data as it leaves Firestore and access the underlying `id` and `ref` fields of the snapshot.
168170

firestore/useCollection.ts

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
QuerySnapshot,
1010
SnapshotOptions,
1111
} from 'firebase/firestore';
12-
import { useEffect, useMemo } from 'react';
12+
import { useCallback, useEffect, useMemo } from 'react';
1313
import { useLoadingValue } from '../util';
1414
import { useIsFirestoreQueryEqual } from './helpers';
1515
import {
@@ -54,12 +54,7 @@ export const useCollection = <T = DocumentData>(
5454
};
5555
}, [ref.current]);
5656

57-
const resArray: CollectionHook<T> = [
58-
value as QuerySnapshot<T>,
59-
loading,
60-
error,
61-
];
62-
return useMemo(() => resArray, resArray);
57+
return [value as QuerySnapshot<T>, loading, error];
6358
};
6459

6560
export const useCollectionOnce = <T = DocumentData>(
@@ -73,27 +68,32 @@ export const useCollectionOnce = <T = DocumentData>(
7368
let effectActive = true;
7469
const ref = useIsFirestoreQueryEqual<Query<T>>(query, reset);
7570

76-
const loadData = async (
77-
query?: Query<T> | null,
78-
options?: Options & OnceOptions
79-
) => {
80-
if (!query) {
81-
setValue(undefined);
82-
return;
83-
}
84-
const get = getDocsFnFromGetOptions(options?.getOptions);
85-
86-
try {
87-
const result = await get(query);
88-
if (effectActive) {
89-
setValue(result);
71+
const loadData = useCallback(
72+
async (query?: Query<T> | null, options?: Options & OnceOptions) => {
73+
if (!query) {
74+
setValue(undefined);
75+
return;
9076
}
91-
} catch (error) {
92-
if (effectActive) {
93-
setError(error as FirestoreError);
77+
const get = getDocsFnFromGetOptions(options?.getOptions);
78+
79+
try {
80+
const result = await get(query);
81+
if (effectActive) {
82+
setValue(result);
83+
}
84+
} catch (error) {
85+
if (effectActive) {
86+
setError(error as FirestoreError);
87+
}
9488
}
95-
}
96-
};
89+
},
90+
[]
91+
);
92+
93+
const reloadData = useCallback(() => loadData(ref.current, options), [
94+
loadData,
95+
ref.current,
96+
]);
9797

9898
useEffect(() => {
9999
loadData(ref.current, options);
@@ -103,58 +103,40 @@ export const useCollectionOnce = <T = DocumentData>(
103103
};
104104
}, [ref.current]);
105105

106-
const resArray: CollectionOnceHook<T> = [
107-
value as QuerySnapshot<T>,
108-
loading,
109-
error,
110-
() => loadData(ref.current, options),
111-
];
112-
return useMemo(() => resArray, resArray);
106+
return [value as QuerySnapshot<T>, loading, error, reloadData];
113107
};
114108

115109
export const useCollectionData = <T = DocumentData>(
116110
query?: Query<T> | null,
117111
options?: DataOptions<T> & InitialValueOptions<T[]>
118112
): CollectionDataHook<T> => {
119-
const snapshotOptions = options?.snapshotOptions;
120113
const [snapshots, loading, error] = useCollection<T>(query, options);
121114

122-
const initialValue = options?.initialValue;
123115
const values = getValuesFromSnapshots<T>(
124116
snapshots,
125-
snapshotOptions,
126-
initialValue
117+
options?.snapshotOptions,
118+
options?.initialValue
127119
);
128120

129-
const resArray: CollectionDataHook<T> = [values, loading, error, snapshots];
130-
return useMemo(() => resArray, resArray);
121+
return [values, loading, error, snapshots];
131122
};
132123

133124
export const useCollectionDataOnce = <T = DocumentData>(
134125
query?: Query<T> | null,
135126
options?: OnceDataOptions<T> & InitialValueOptions<T[]>
136127
): CollectionDataOnceHook<T> => {
137-
const snapshotOptions = options?.snapshotOptions;
138-
const [snapshots, loading, error, loadData] = useCollectionOnce<T>(
128+
const [snapshots, loading, error, reloadData] = useCollectionOnce<T>(
139129
query,
140130
options
141131
);
142132

143-
const initialValue = options?.initialValue;
144133
const values = getValuesFromSnapshots<T>(
145134
snapshots,
146-
snapshotOptions,
147-
initialValue
135+
options?.snapshotOptions,
136+
options?.initialValue
148137
);
149138

150-
const resArray: CollectionDataOnceHook<T> = [
151-
values,
152-
loading,
153-
error,
154-
snapshots,
155-
loadData,
156-
];
157-
return useMemo(() => resArray, resArray);
139+
return [values, loading, error, snapshots, reloadData];
158140
};
159141

160142
const getValuesFromSnapshots = <T>(

firestore/useDocument.ts

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
onSnapshot,
1010
SnapshotOptions,
1111
} from 'firebase/firestore';
12-
import { useEffect, useMemo } from 'react';
12+
import { useCallback, useEffect, useMemo } from 'react';
1313
import { useLoadingValue } from '../util';
1414
import { useIsFirestoreRefEqual } from './helpers';
1515
import {
@@ -54,12 +54,7 @@ export const useDocument = <T = DocumentData>(
5454
};
5555
}, [ref.current]);
5656

57-
const resArray: DocumentHook<T> = [
58-
value as DocumentSnapshot<T>,
59-
loading,
60-
error,
61-
];
62-
return useMemo(() => resArray, resArray);
57+
return [value as DocumentSnapshot<T>, loading, error];
6358
};
6459

6560
export const useDocumentOnce = <T = DocumentData>(
@@ -73,27 +68,32 @@ export const useDocumentOnce = <T = DocumentData>(
7368
let effectActive = true;
7469
const ref = useIsFirestoreRefEqual<DocumentReference<T>>(docRef, reset);
7570

76-
const loadData = async (
77-
reference?: DocumentReference<T> | null,
78-
options?: OnceOptions
79-
) => {
80-
if (!reference) {
81-
setValue(undefined);
82-
return;
83-
}
84-
const get = getDocFnFromGetOptions(options?.getOptions);
85-
86-
try {
87-
const result = await get(reference);
88-
if (effectActive) {
89-
setValue(result);
71+
const loadData = useCallback(
72+
async (reference?: DocumentReference<T> | null, options?: OnceOptions) => {
73+
if (!reference) {
74+
setValue(undefined);
75+
return;
9076
}
91-
} catch (error) {
92-
if (effectActive) {
93-
setError(error as FirestoreError);
77+
const get = getDocFnFromGetOptions(options?.getOptions);
78+
79+
try {
80+
const result = await get(reference);
81+
if (effectActive) {
82+
setValue(result);
83+
}
84+
} catch (error) {
85+
if (effectActive) {
86+
setError(error as FirestoreError);
87+
}
9488
}
95-
}
96-
};
89+
},
90+
[]
91+
);
92+
93+
const reloadData = useCallback(() => loadData(ref.current, options), [
94+
loadData,
95+
ref.current,
96+
]);
9797

9898
useEffect(() => {
9999
if (!ref.current) {
@@ -108,13 +108,7 @@ export const useDocumentOnce = <T = DocumentData>(
108108
};
109109
}, [ref.current]);
110110

111-
const resArray: DocumentOnceHook<T> = [
112-
value as DocumentSnapshot<T>,
113-
loading,
114-
error,
115-
() => loadData(ref.current, options),
116-
];
117-
return useMemo(() => resArray, resArray);
111+
return [value as DocumentSnapshot<T>, loading, error, reloadData];
118112
};
119113

120114
export const useDocumentData = <T = DocumentData>(
@@ -129,15 +123,14 @@ export const useDocumentData = <T = DocumentData>(
129123
options?.initialValue
130124
);
131125

132-
const resArray: DocumentDataHook<T> = [value, loading, error, snapshot];
133-
return useMemo(() => resArray, resArray);
126+
return [value, loading, error, snapshot];
134127
};
135128

136129
export const useDocumentDataOnce = <T = DocumentData>(
137130
docRef?: DocumentReference<T> | null,
138131
options?: OnceDataOptions<T> & InitialValueOptions<T>
139132
): DocumentDataOnceHook<T> => {
140-
const [snapshot, loading, error, loadData] = useDocumentOnce<T>(
133+
const [snapshot, loading, error, reloadData] = useDocumentOnce<T>(
141134
docRef,
142135
options
143136
);
@@ -148,14 +141,7 @@ export const useDocumentDataOnce = <T = DocumentData>(
148141
options?.initialValue
149142
);
150143

151-
const resArray: DocumentDataOnceHook<T> = [
152-
value,
153-
loading,
154-
error,
155-
snapshot,
156-
loadData,
157-
];
158-
return useMemo(() => resArray, resArray);
144+
return [value, loading, error, snapshot, reloadData];
159145
};
160146

161147
const getDocFnFromGetOptions = (

0 commit comments

Comments
 (0)