react-native-onyx 2.0.32 → 2.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DevTools.js +2 -2
- package/dist/Onyx.js +9 -4
- package/dist/OnyxUtils.d.ts +5 -4
- package/dist/OnyxUtils.js +24 -21
- package/dist/storage/providers/MemoryOnlyProvider.js +1 -5
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +12 -12
- package/dist/withOnyx.js +2 -1
- package/package.json +1 -1
package/dist/DevTools.js
CHANGED
|
@@ -11,8 +11,8 @@ class DevTools {
|
|
|
11
11
|
try {
|
|
12
12
|
// We don't want to augment the window type in a library code, so we use type assertion instead
|
|
13
13
|
// eslint-disable-next-line no-underscore-dangle, @typescript-eslint/no-explicit-any
|
|
14
|
-
const reduxDevtools = window.__REDUX_DEVTOOLS_EXTENSION__;
|
|
15
|
-
if ((options
|
|
14
|
+
const reduxDevtools = typeof window === 'undefined' ? undefined : window.__REDUX_DEVTOOLS_EXTENSION__;
|
|
15
|
+
if ((options === null || options === void 0 ? void 0 : options.remote) || !reduxDevtools) {
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
return reduxDevtools.connect(options);
|
package/dist/Onyx.js
CHANGED
|
@@ -221,7 +221,7 @@ function set(key, value) {
|
|
|
221
221
|
* @param data object keyed by ONYXKEYS and the values to set
|
|
222
222
|
*/
|
|
223
223
|
function multiSet(data) {
|
|
224
|
-
const keyValuePairs = OnyxUtils_1.default.prepareKeyValuePairsForStorage(data);
|
|
224
|
+
const keyValuePairs = OnyxUtils_1.default.prepareKeyValuePairsForStorage(data, true);
|
|
225
225
|
const updatePromises = keyValuePairs.map(([key, value]) => {
|
|
226
226
|
const prevValue = OnyxCache_1.default.getValue(key, false);
|
|
227
227
|
// Update cache and optimistically inform subscribers on the next tick
|
|
@@ -256,7 +256,7 @@ function merge(key, changes) {
|
|
|
256
256
|
const mergeQueue = OnyxUtils_1.default.getMergeQueue();
|
|
257
257
|
const mergeQueuePromise = OnyxUtils_1.default.getMergeQueuePromise();
|
|
258
258
|
// Top-level undefined values are ignored
|
|
259
|
-
// Therefore we need to prevent adding them to the merge queue
|
|
259
|
+
// Therefore, we need to prevent adding them to the merge queue
|
|
260
260
|
if (changes === undefined) {
|
|
261
261
|
return mergeQueue[key] ? mergeQueuePromise[key] : Promise.resolve();
|
|
262
262
|
}
|
|
@@ -369,8 +369,13 @@ function mergeCollection(collectionKey, collection) {
|
|
|
369
369
|
obj[key] = mergedCollection[key];
|
|
370
370
|
return obj;
|
|
371
371
|
}, {});
|
|
372
|
-
|
|
373
|
-
|
|
372
|
+
// When (multi-)merging the values with the existing values in storage,
|
|
373
|
+
// we don't want to remove nested null values from the data that we pass to the storage layer,
|
|
374
|
+
// because the storage layer uses them to remove nested keys from storage natively.
|
|
375
|
+
const keyValuePairsForExistingCollection = OnyxUtils_1.default.prepareKeyValuePairsForStorage(existingKeyCollection, false);
|
|
376
|
+
// We can safely remove nested null values when using (multi-)set,
|
|
377
|
+
// because we will simply overwrite the existing values in storage.
|
|
378
|
+
const keyValuePairsForNewCollection = OnyxUtils_1.default.prepareKeyValuePairsForStorage(newCollection, true);
|
|
374
379
|
const promises = [];
|
|
375
380
|
// New keys will be added via multiSet while existing keys will be updated using multiMerge
|
|
376
381
|
// This is because setting a key that doesn't exist yet with multiMerge will throw errors
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -165,11 +165,12 @@ type RemoveNullValuesOutput = {
|
|
|
165
165
|
};
|
|
166
166
|
/**
|
|
167
167
|
* Removes a key from storage if the value is null.
|
|
168
|
-
* Otherwise removes all nested null values in objects
|
|
168
|
+
* Otherwise removes all nested null values in objects,
|
|
169
|
+
* if shouldRemoveNestedNulls is true and returns the object.
|
|
169
170
|
*
|
|
170
171
|
* @returns The value without null values and a boolean "wasRemoved", which indicates if the key got removed completely
|
|
171
172
|
*/
|
|
172
|
-
declare function removeNullValues(key: OnyxKey, value: OnyxValue<OnyxKey
|
|
173
|
+
declare function removeNullValues(key: OnyxKey, value: OnyxValue<OnyxKey>, shouldRemoveNestedNulls?: boolean): RemoveNullValuesOutput;
|
|
173
174
|
/**
|
|
174
175
|
* Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
|
|
175
176
|
* This method transforms an object like {'@MyApp_user': myUserValue, '@MyApp_key': myKeyValue}
|
|
@@ -177,13 +178,13 @@ declare function removeNullValues(key: OnyxKey, value: OnyxValue<OnyxKey>): Remo
|
|
|
177
178
|
|
|
178
179
|
* @return an array of key - value pairs <[key, value]>
|
|
179
180
|
*/
|
|
180
|
-
declare function prepareKeyValuePairsForStorage(data: Record<OnyxKey, OnyxValue<OnyxKey
|
|
181
|
+
declare function prepareKeyValuePairsForStorage(data: Record<OnyxKey, OnyxValue<OnyxKey>>, shouldRemoveNestedNulls: boolean): Array<[OnyxKey, OnyxValue<OnyxKey>]>;
|
|
181
182
|
/**
|
|
182
183
|
* Merges an array of changes with an existing value
|
|
183
184
|
*
|
|
184
185
|
* @param changes Array of changes that should be applied to the existing value
|
|
185
186
|
*/
|
|
186
|
-
declare function applyMerge(existingValue: OnyxValue<OnyxKey>, changes: Array<OnyxValue<OnyxKey>>,
|
|
187
|
+
declare function applyMerge(existingValue: OnyxValue<OnyxKey>, changes: Array<OnyxValue<OnyxKey>>, shouldRemoveNestedNulls: boolean): OnyxValue<OnyxKey>;
|
|
187
188
|
/**
|
|
188
189
|
* Merge user provided default key value pairs.
|
|
189
190
|
*/
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -363,6 +363,7 @@ function keysChanged(collectionKey, partialCollection, notifyRegularSubscibers =
|
|
|
363
363
|
// We prepare the "cached collection" which is the entire collection + the new partial data that
|
|
364
364
|
// was merged in via mergeCollection().
|
|
365
365
|
const cachedCollection = getCachedCollection(collectionKey);
|
|
366
|
+
const cachedCollectionWithoutNestedNulls = utils_1.default.removeNestedNullValues(cachedCollection);
|
|
366
367
|
// Regular Onyx.connect() subscriber found.
|
|
367
368
|
if (typeof subscriber.callback === 'function') {
|
|
368
369
|
if (!notifyRegularSubscibers) {
|
|
@@ -372,7 +373,7 @@ function keysChanged(collectionKey, partialCollection, notifyRegularSubscibers =
|
|
|
372
373
|
// send the whole cached collection.
|
|
373
374
|
if (isSubscribedToCollectionKey) {
|
|
374
375
|
if (subscriber.waitForCollectionCallback) {
|
|
375
|
-
subscriber.callback(
|
|
376
|
+
subscriber.callback(cachedCollectionWithoutNestedNulls);
|
|
376
377
|
continue;
|
|
377
378
|
}
|
|
378
379
|
// If they are not using waitForCollectionCallback then we notify the subscriber with
|
|
@@ -380,7 +381,7 @@ function keysChanged(collectionKey, partialCollection, notifyRegularSubscibers =
|
|
|
380
381
|
const dataKeys = Object.keys(partialCollection !== null && partialCollection !== void 0 ? partialCollection : {});
|
|
381
382
|
for (let j = 0; j < dataKeys.length; j++) {
|
|
382
383
|
const dataKey = dataKeys[j];
|
|
383
|
-
subscriber.callback(
|
|
384
|
+
subscriber.callback(cachedCollectionWithoutNestedNulls[dataKey], dataKey);
|
|
384
385
|
}
|
|
385
386
|
continue;
|
|
386
387
|
}
|
|
@@ -388,7 +389,7 @@ function keysChanged(collectionKey, partialCollection, notifyRegularSubscibers =
|
|
|
388
389
|
// notify them with the cached data for that key only.
|
|
389
390
|
if (isSubscribedToCollectionMemberKey) {
|
|
390
391
|
const subscriberCallback = subscriber.callback;
|
|
391
|
-
subscriberCallback(
|
|
392
|
+
subscriberCallback(cachedCollectionWithoutNestedNulls[subscriber.key], subscriber.key);
|
|
392
393
|
continue;
|
|
393
394
|
}
|
|
394
395
|
continue;
|
|
@@ -507,12 +508,14 @@ function keyChanged(key, data, prevData, canUpdateSubscriber = () => true, notif
|
|
|
507
508
|
}
|
|
508
509
|
if (isCollectionKey(subscriber.key) && subscriber.waitForCollectionCallback) {
|
|
509
510
|
const cachedCollection = getCachedCollection(subscriber.key);
|
|
510
|
-
|
|
511
|
-
|
|
511
|
+
const cachedCollectionWithoutNestedNulls = utils_1.default.removeNestedNullValues(cachedCollection);
|
|
512
|
+
cachedCollectionWithoutNestedNulls[key] = data;
|
|
513
|
+
subscriber.callback(cachedCollectionWithoutNestedNulls);
|
|
512
514
|
continue;
|
|
513
515
|
}
|
|
516
|
+
const dataWithoutNestedNulls = utils_1.default.removeNestedNullValues(data);
|
|
514
517
|
const subscriberCallback = subscriber.callback;
|
|
515
|
-
subscriberCallback(
|
|
518
|
+
subscriberCallback(dataWithoutNestedNulls, key);
|
|
516
519
|
continue;
|
|
517
520
|
}
|
|
518
521
|
// Subscriber connected via withOnyx() HOC
|
|
@@ -620,7 +623,8 @@ function sendDataToConnection(mapping, val, matchedKey, isBatched) {
|
|
|
620
623
|
}
|
|
621
624
|
return;
|
|
622
625
|
}
|
|
623
|
-
|
|
626
|
+
const valuesWithoutNestedNulls = utils_1.default.removeNestedNullValues(val);
|
|
627
|
+
(_b = (_a = mapping).callback) === null || _b === void 0 ? void 0 : _b.call(_a, valuesWithoutNestedNulls, matchedKey);
|
|
624
628
|
}
|
|
625
629
|
/**
|
|
626
630
|
* We check to see if this key is flagged as safe for eviction and add it to the recentlyAccessedKeys list so that when we
|
|
@@ -794,11 +798,12 @@ function hasPendingMergeForKey(key) {
|
|
|
794
798
|
}
|
|
795
799
|
/**
|
|
796
800
|
* Removes a key from storage if the value is null.
|
|
797
|
-
* Otherwise removes all nested null values in objects
|
|
801
|
+
* Otherwise removes all nested null values in objects,
|
|
802
|
+
* if shouldRemoveNestedNulls is true and returns the object.
|
|
798
803
|
*
|
|
799
804
|
* @returns The value without null values and a boolean "wasRemoved", which indicates if the key got removed completely
|
|
800
805
|
*/
|
|
801
|
-
function removeNullValues(key, value) {
|
|
806
|
+
function removeNullValues(key, value, shouldRemoveNestedNulls = true) {
|
|
802
807
|
if (value === null) {
|
|
803
808
|
remove(key);
|
|
804
809
|
return { value, wasRemoved: true };
|
|
@@ -806,7 +811,7 @@ function removeNullValues(key, value) {
|
|
|
806
811
|
// We can remove all null values in an object by merging it with itself
|
|
807
812
|
// utils.fastMerge recursively goes through the object and removes all null values
|
|
808
813
|
// Passing two identical objects as source and target to fastMerge will not change it, but only remove the null values
|
|
809
|
-
return { value: utils_1.default.removeNestedNullValues(value), wasRemoved: false };
|
|
814
|
+
return { value: shouldRemoveNestedNulls ? utils_1.default.removeNestedNullValues(value) : value, wasRemoved: false };
|
|
810
815
|
}
|
|
811
816
|
/**
|
|
812
817
|
* Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
|
|
@@ -815,30 +820,28 @@ function removeNullValues(key, value) {
|
|
|
815
820
|
|
|
816
821
|
* @return an array of key - value pairs <[key, value]>
|
|
817
822
|
*/
|
|
818
|
-
function prepareKeyValuePairsForStorage(data) {
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
return;
|
|
823
|
+
function prepareKeyValuePairsForStorage(data, shouldRemoveNestedNulls) {
|
|
824
|
+
return Object.entries(data).reduce((pairs, [key, value]) => {
|
|
825
|
+
const { value: valueAfterRemoving, wasRemoved } = removeNullValues(key, value, shouldRemoveNestedNulls);
|
|
826
|
+
if (!wasRemoved) {
|
|
827
|
+
pairs.push([key, valueAfterRemoving]);
|
|
824
828
|
}
|
|
825
|
-
|
|
826
|
-
});
|
|
827
|
-
return keyValuePairs;
|
|
829
|
+
return pairs;
|
|
830
|
+
}, []);
|
|
828
831
|
}
|
|
829
832
|
/**
|
|
830
833
|
* Merges an array of changes with an existing value
|
|
831
834
|
*
|
|
832
835
|
* @param changes Array of changes that should be applied to the existing value
|
|
833
836
|
*/
|
|
834
|
-
function applyMerge(existingValue, changes,
|
|
837
|
+
function applyMerge(existingValue, changes, shouldRemoveNestedNulls) {
|
|
835
838
|
const lastChange = changes === null || changes === void 0 ? void 0 : changes.at(-1);
|
|
836
839
|
if (Array.isArray(lastChange)) {
|
|
837
840
|
return lastChange;
|
|
838
841
|
}
|
|
839
842
|
if (changes.some((change) => change && typeof change === 'object')) {
|
|
840
843
|
// Object values are then merged one after the other
|
|
841
|
-
return changes.reduce((modifiedData, change) => utils_1.default.fastMerge(modifiedData, change,
|
|
844
|
+
return changes.reduce((modifiedData, change) => utils_1.default.fastMerge(modifiedData, change, shouldRemoveNestedNulls), existingValue || {});
|
|
842
845
|
}
|
|
843
846
|
// If we have anything else we can't merge it so we'll
|
|
844
847
|
// simply return the last value that was queued
|
|
@@ -55,11 +55,7 @@ const provider = {
|
|
|
55
55
|
*/
|
|
56
56
|
multiSet(pairs) {
|
|
57
57
|
const setPromises = underscore_1.default.map(pairs, ([key, value]) => this.setItem(key, value));
|
|
58
|
-
return
|
|
59
|
-
Promise.all(setPromises).then(() => {
|
|
60
|
-
resolve(undefined);
|
|
61
|
-
});
|
|
62
|
-
});
|
|
58
|
+
return Promise.all(setPromises).then(() => undefined);
|
|
63
59
|
},
|
|
64
60
|
/**
|
|
65
61
|
* Merging an existing value with a new one
|
package/dist/utils.d.ts
CHANGED
|
@@ -4,15 +4,15 @@ type EmptyValue = EmptyObject | null | undefined;
|
|
|
4
4
|
/** Checks whether the given object is an object and not null/undefined. */
|
|
5
5
|
declare function isEmptyObject<T>(obj: T | EmptyValue): obj is EmptyValue;
|
|
6
6
|
/**
|
|
7
|
-
* Merges two objects and removes null values if "
|
|
7
|
+
* Merges two objects and removes null values if "shouldRemoveNestedNulls" is set to true
|
|
8
8
|
*
|
|
9
9
|
* We generally want to remove null values from objects written to disk and cache, because it decreases the amount of data stored in memory and on disk.
|
|
10
10
|
* On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
|
|
11
11
|
* To be consistent with the behaviour for merge, we'll also want to remove null values for "set" operations.
|
|
12
12
|
*/
|
|
13
|
-
declare function fastMerge<TObject extends Record<string, unknown>>(target: TObject | null, source: TObject | null,
|
|
13
|
+
declare function fastMerge<TObject extends Record<string, unknown>>(target: TObject | null, source: TObject | null, shouldRemoveNestedNulls?: boolean): TObject | null;
|
|
14
14
|
/** Deep removes the nested null values from the given value. */
|
|
15
|
-
declare function removeNestedNullValues(value: unknown[] |
|
|
15
|
+
declare function removeNestedNullValues<TObject extends Record<string, unknown>>(value: unknown | unknown[] | TObject): Record<string, unknown> | unknown[] | null;
|
|
16
16
|
/** Formats the action name by uppercasing and adding the key if provided. */
|
|
17
17
|
declare function formatActionName(method: string, key?: OnyxKey): string;
|
|
18
18
|
declare const _default: {
|
package/dist/utils.js
CHANGED
|
@@ -17,14 +17,14 @@ function isMergeableObject(value) {
|
|
|
17
17
|
* Merges the source object into the target object.
|
|
18
18
|
* @param target - The target object.
|
|
19
19
|
* @param source - The source object.
|
|
20
|
-
* @param
|
|
20
|
+
* @param shouldRemoveNestedNulls - If true, null object values will be removed.
|
|
21
21
|
* @returns - The merged object.
|
|
22
22
|
*/
|
|
23
|
-
function mergeObject(target, source,
|
|
23
|
+
function mergeObject(target, source, shouldRemoveNestedNulls = true) {
|
|
24
24
|
const destination = {};
|
|
25
25
|
// First we want to copy over all keys from the target into the destination object,
|
|
26
26
|
// in case "target" is a mergable object.
|
|
27
|
-
// If "
|
|
27
|
+
// If "shouldRemoveNestedNulls" is true, we want to remove null values from the merged object
|
|
28
28
|
// and therefore we need to omit keys where either the source or target value is null.
|
|
29
29
|
if (isMergeableObject(target)) {
|
|
30
30
|
const targetKeys = Object.keys(target);
|
|
@@ -32,10 +32,10 @@ function mergeObject(target, source, shouldRemoveNullObjectValues = true) {
|
|
|
32
32
|
const key = targetKeys[i];
|
|
33
33
|
const sourceValue = source === null || source === void 0 ? void 0 : source[key];
|
|
34
34
|
const targetValue = target === null || target === void 0 ? void 0 : target[key];
|
|
35
|
-
// If "
|
|
35
|
+
// If "shouldRemoveNestedNulls" is true, we want to remove null values from the merged object.
|
|
36
36
|
// Therefore, if either target or source value is null, we want to prevent the key from being set.
|
|
37
37
|
const isSourceOrTargetNull = targetValue === null || sourceValue === null;
|
|
38
|
-
const shouldOmitTargetKey =
|
|
38
|
+
const shouldOmitTargetKey = shouldRemoveNestedNulls && isSourceOrTargetNull;
|
|
39
39
|
if (!shouldOmitTargetKey) {
|
|
40
40
|
destination[key] = targetValue;
|
|
41
41
|
}
|
|
@@ -48,13 +48,13 @@ function mergeObject(target, source, shouldRemoveNullObjectValues = true) {
|
|
|
48
48
|
const sourceValue = source === null || source === void 0 ? void 0 : source[key];
|
|
49
49
|
const targetValue = target === null || target === void 0 ? void 0 : target[key];
|
|
50
50
|
// If undefined is passed as the source value for a key, we want to generally ignore it.
|
|
51
|
-
// If "
|
|
51
|
+
// If "shouldRemoveNestedNulls" is set to true and the source value is null,
|
|
52
52
|
// we don't want to set/merge the source value into the merged object.
|
|
53
|
-
const shouldIgnoreNullSourceValue =
|
|
53
|
+
const shouldIgnoreNullSourceValue = shouldRemoveNestedNulls && sourceValue === null;
|
|
54
54
|
const shouldOmitSourceKey = sourceValue === undefined || shouldIgnoreNullSourceValue;
|
|
55
55
|
if (!shouldOmitSourceKey) {
|
|
56
56
|
// If the source value is a mergable object, we want to merge it into the target value.
|
|
57
|
-
// If "
|
|
57
|
+
// If "shouldRemoveNestedNulls" is true, "fastMerge" will recursively
|
|
58
58
|
// remove nested null values from the merged object.
|
|
59
59
|
// If source value is any other value we need to set the source value it directly.
|
|
60
60
|
if (isMergeableObject(sourceValue)) {
|
|
@@ -62,7 +62,7 @@ function mergeObject(target, source, shouldRemoveNullObjectValues = true) {
|
|
|
62
62
|
// so that we can still use "fastMerge" to merge the source value,
|
|
63
63
|
// to ensure that nested null values are removed from the merged object.
|
|
64
64
|
const targetValueWithFallback = (targetValue !== null && targetValue !== void 0 ? targetValue : {});
|
|
65
|
-
destination[key] = fastMerge(targetValueWithFallback, sourceValue,
|
|
65
|
+
destination[key] = fastMerge(targetValueWithFallback, sourceValue, shouldRemoveNestedNulls);
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
68
|
destination[key] = sourceValue;
|
|
@@ -72,20 +72,20 @@ function mergeObject(target, source, shouldRemoveNullObjectValues = true) {
|
|
|
72
72
|
return destination;
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
|
-
* Merges two objects and removes null values if "
|
|
75
|
+
* Merges two objects and removes null values if "shouldRemoveNestedNulls" is set to true
|
|
76
76
|
*
|
|
77
77
|
* We generally want to remove null values from objects written to disk and cache, because it decreases the amount of data stored in memory and on disk.
|
|
78
78
|
* On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
|
|
79
79
|
* To be consistent with the behaviour for merge, we'll also want to remove null values for "set" operations.
|
|
80
80
|
*/
|
|
81
|
-
function fastMerge(target, source,
|
|
81
|
+
function fastMerge(target, source, shouldRemoveNestedNulls = true) {
|
|
82
82
|
// We have to ignore arrays and nullish values here,
|
|
83
83
|
// otherwise "mergeObject" will throw an error,
|
|
84
84
|
// because it expects an object as "source"
|
|
85
85
|
if (Array.isArray(source) || source === null || source === undefined) {
|
|
86
86
|
return source;
|
|
87
87
|
}
|
|
88
|
-
return mergeObject(target, source,
|
|
88
|
+
return mergeObject(target, source, shouldRemoveNestedNulls);
|
|
89
89
|
}
|
|
90
90
|
/** Deep removes the nested null values from the given value. */
|
|
91
91
|
function removeNestedNullValues(value) {
|
package/dist/withOnyx.js
CHANGED
|
@@ -298,8 +298,9 @@ function default_1(mapOnyxToState, shouldDelayUpdates = false) {
|
|
|
298
298
|
// that should not be passed to a wrapped component
|
|
299
299
|
let stateToPass = underscore_1.default.omit(this.state, 'loading');
|
|
300
300
|
stateToPass = underscore_1.default.omit(stateToPass, underscore_1.default.isNull);
|
|
301
|
+
const stateToPassWithoutNestedNulls = utils_1.default.removeNestedNullValues(stateToPass);
|
|
301
302
|
// Spreading props and state is necessary in an HOC where the data cannot be predicted
|
|
302
|
-
return (react_1.default.createElement(WrappedComponent, Object.assign({ markReadyForHydration: this.flushPendingSetStates }, propsToPass,
|
|
303
|
+
return (react_1.default.createElement(WrappedComponent, Object.assign({ markReadyForHydration: this.flushPendingSetStates }, propsToPass, stateToPassWithoutNestedNulls, { ref: this.props.forwardedRef })));
|
|
303
304
|
}
|
|
304
305
|
}
|
|
305
306
|
withOnyx.propTypes = {
|