react-native-onyx 1.0.131 → 2.0.2
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/API.md +83 -22
- package/README.md +3 -5
- package/dist/DevTools.d.ts +23 -0
- package/{lib → dist}/DevTools.js +16 -18
- package/dist/Logger.js +32 -0
- package/dist/MDTable.d.ts +36 -0
- package/{lib → dist}/MDTable.js +12 -17
- package/{lib → dist}/Onyx.js +278 -477
- package/dist/OnyxCache.d.ts +121 -0
- package/{lib → dist}/OnyxCache.js +16 -53
- package/{lib/Str.js → dist/Str.d.ts} +2 -11
- package/dist/Str.js +31 -0
- package/dist/SyncQueue.d.ts +32 -0
- package/{lib → dist}/SyncQueue.js +9 -11
- package/dist/batch.d.ts +2 -0
- package/dist/batch.js +4 -0
- package/dist/batch.native.d.ts +2 -0
- package/dist/batch.native.js +4 -0
- package/dist/compose.d.ts +19 -0
- package/{lib → dist}/compose.js +5 -8
- package/dist/createDeferredTask.d.ts +12 -0
- package/{lib → dist}/createDeferredTask.js +4 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +10 -0
- package/dist/metrics/PerformanceUtils.d.ts +14 -0
- package/{lib → dist}/metrics/PerformanceUtils.js +16 -16
- package/dist/metrics/index.d.ts +4 -0
- package/dist/metrics/index.js +14 -0
- package/dist/metrics/index.native.d.ts +43 -0
- package/{lib → dist}/metrics/index.native.js +80 -102
- package/{lib/storage/NativeStorage.js → dist/storage/NativeStorage.d.ts} +1 -2
- package/dist/storage/NativeStorage.js +7 -0
- package/dist/storage/WebStorage.d.ts +19 -0
- package/{lib → dist}/storage/WebStorage.js +24 -34
- package/dist/storage/__mocks__/index.d.ts +23 -0
- package/{lib → dist}/storage/__mocks__/index.js +17 -19
- package/{lib/storage/index.web.js → dist/storage/index.d.ts} +1 -2
- package/dist/storage/index.js +7 -0
- package/{lib/storage/index.native.js → dist/storage/index.native.d.ts} +1 -2
- package/dist/storage/index.native.js +7 -0
- package/dist/storage/providers/IDBKeyVal.d.ts +26 -0
- package/{lib → dist}/storage/providers/IDBKeyVal.js +38 -52
- package/dist/storage/providers/SQLiteStorage.d.ts +52 -0
- package/{lib → dist}/storage/providers/SQLiteStorage.js +27 -42
- package/{lib → dist}/utils.js +14 -27
- package/{lib → dist}/withOnyx.js +122 -159
- package/package.json +23 -54
- package/dist/web.development.js +0 -4308
- package/dist/web.development.js.map +0 -1
- package/dist/web.min.js +0 -2
- package/dist/web.min.js.map +0 -1
- package/lib/Logger.js +0 -31
- package/lib/batch.js +0 -3
- package/lib/batch.native.js +0 -3
- package/lib/index.d.ts +0 -6
- package/lib/index.js +0 -5
- package/lib/metrics/index.web.js +0 -10
- package/native.js +0 -11
- package/web.js +0 -12
- /package/{lib → dist}/Logger.d.ts +0 -0
- /package/{lib → dist}/Onyx.d.ts +0 -0
- /package/{lib → dist}/types.d.ts +0 -0
- /package/{lib → dist}/utils.d.ts +0 -0
- /package/{lib → dist}/withOnyx.d.ts +0 -0
package/{lib → dist}/withOnyx.js
RENAMED
|
@@ -1,19 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
29
|
/**
|
|
2
30
|
* This is a higher order component that provides the ability to map a state property directly to
|
|
3
31
|
* something in Onyx (a key/value store). That way, as soon as data in Onyx changes, the state will be set and the view
|
|
4
32
|
* will automatically change to reflect the new data.
|
|
5
33
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
34
|
+
const prop_types_1 = __importDefault(require("prop-types"));
|
|
35
|
+
const react_1 = __importDefault(require("react"));
|
|
36
|
+
const underscore_1 = __importDefault(require("underscore"));
|
|
37
|
+
const Onyx_1 = __importDefault(require("./Onyx"));
|
|
38
|
+
const Str = __importStar(require("./Str"));
|
|
39
|
+
const utils_1 = __importDefault(require("./utils"));
|
|
13
40
|
// This is a list of keys that can exist on a `mapping`, but are not directly related to loading data from Onyx. When the keys of a mapping are looped over to check
|
|
14
41
|
// if a key has changed, it's a good idea to skip looking at these properties since they would have unexpected results.
|
|
15
42
|
const mappingPropertiesToIgnoreChangesTo = ['initialValue', 'allowStaleData'];
|
|
16
|
-
|
|
17
43
|
/**
|
|
18
44
|
* Returns the display name of a component
|
|
19
45
|
*
|
|
@@ -23,7 +49,6 @@ const mappingPropertiesToIgnoreChangesTo = ['initialValue', 'allowStaleData'];
|
|
|
23
49
|
function getDisplayName(component) {
|
|
24
50
|
return component.displayName || component.name || 'Component';
|
|
25
51
|
}
|
|
26
|
-
|
|
27
52
|
/**
|
|
28
53
|
* Removes all the keys from state that are unrelated to the onyx data being mapped to the component.
|
|
29
54
|
*
|
|
@@ -31,82 +56,66 @@ function getDisplayName(component) {
|
|
|
31
56
|
* @param {Object} onyxToStateMapping the object holding all of the mapping configuration for the component
|
|
32
57
|
* @returns {Object}
|
|
33
58
|
*/
|
|
34
|
-
const getOnyxDataFromState = (state, onyxToStateMapping) =>
|
|
35
|
-
|
|
36
|
-
export default function (mapOnyxToState, shouldDelayUpdates = false) {
|
|
59
|
+
const getOnyxDataFromState = (state, onyxToStateMapping) => underscore_1.default.pick(state, underscore_1.default.keys(onyxToStateMapping));
|
|
60
|
+
function default_1(mapOnyxToState, shouldDelayUpdates = false) {
|
|
37
61
|
// A list of keys that must be present in tempState before we can render the WrappedComponent
|
|
38
|
-
const requiredKeysForInit =
|
|
62
|
+
const requiredKeysForInit = underscore_1.default.chain(mapOnyxToState)
|
|
39
63
|
.omit((config) => config.initWithStoredValues === false)
|
|
40
64
|
.keys()
|
|
41
65
|
.value();
|
|
42
66
|
return (WrappedComponent) => {
|
|
43
67
|
const displayName = getDisplayName(WrappedComponent);
|
|
44
|
-
class withOnyx extends
|
|
45
|
-
pendingSetStates = [];
|
|
46
|
-
|
|
68
|
+
class withOnyx extends react_1.default.Component {
|
|
47
69
|
constructor(props) {
|
|
48
70
|
super(props);
|
|
71
|
+
this.pendingSetStates = [];
|
|
49
72
|
this.shouldDelayUpdates = shouldDelayUpdates;
|
|
50
73
|
this.setWithOnyxState = this.setWithOnyxState.bind(this);
|
|
51
74
|
this.flushPendingSetStates = this.flushPendingSetStates.bind(this);
|
|
52
|
-
|
|
53
75
|
// This stores all the Onyx connection IDs to be used when the component unmounts so everything can be
|
|
54
76
|
// disconnected. It is a key value store with the format {[mapping.key]: connectionID}.
|
|
55
77
|
this.activeConnectionIDs = {};
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
resultObj[propertyName] = value;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return resultObj;
|
|
83
|
-
},
|
|
84
|
-
{},
|
|
85
|
-
);
|
|
86
|
-
|
|
78
|
+
const cachedState = underscore_1.default.reduce(mapOnyxToState, (resultObj, mapping, propertyName) => {
|
|
79
|
+
const key = Str.result(mapping.key, props);
|
|
80
|
+
let value = Onyx_1.default.tryGetCachedValue(key, mapping);
|
|
81
|
+
if (!value && mapping.initialValue) {
|
|
82
|
+
value = mapping.initialValue;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* If we have a pending merge for a key it could mean that data is being set via Onyx.merge() and someone expects a component to have this data immediately.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
*
|
|
89
|
+
* Onyx.merge('report_123', value);
|
|
90
|
+
* Navigation.navigate(route); // Where "route" expects the "value" to be available immediately once rendered.
|
|
91
|
+
*
|
|
92
|
+
* In reality, Onyx.merge() will only update the subscriber after all merges have been batched and the previous value is retrieved via a get() (returns a promise).
|
|
93
|
+
* So, we won't use the cache optimization here as it will lead us to arbitrarily defer various actions in the application code.
|
|
94
|
+
*/
|
|
95
|
+
if ((value !== undefined && !Onyx_1.default.hasPendingMergeForKey(key)) || mapping.allowStaleData) {
|
|
96
|
+
// eslint-disable-next-line no-param-reassign
|
|
97
|
+
resultObj[propertyName] = value;
|
|
98
|
+
}
|
|
99
|
+
return resultObj;
|
|
100
|
+
}, {});
|
|
87
101
|
// If we have all the data we need, then we can render the component immediately
|
|
88
|
-
cachedState.loading =
|
|
89
|
-
|
|
102
|
+
cachedState.loading = underscore_1.default.size(cachedState) < requiredKeysForInit.length;
|
|
90
103
|
// Object holding the temporary initial state for the component while we load the various Onyx keys
|
|
91
104
|
this.tempState = cachedState;
|
|
92
|
-
|
|
93
105
|
this.state = cachedState;
|
|
94
106
|
}
|
|
95
|
-
|
|
96
107
|
componentDidMount() {
|
|
97
108
|
const onyxDataFromState = getOnyxDataFromState(this.state, mapOnyxToState);
|
|
98
|
-
|
|
99
109
|
// Subscribe each of the state properties to the proper Onyx key
|
|
100
|
-
|
|
101
|
-
if (
|
|
110
|
+
underscore_1.default.each(mapOnyxToState, (mapping, propertyName) => {
|
|
111
|
+
if (underscore_1.default.includes(mappingPropertiesToIgnoreChangesTo, propertyName)) {
|
|
102
112
|
return;
|
|
103
113
|
}
|
|
104
|
-
const key = Str.result(mapping.key, {
|
|
114
|
+
const key = Str.result(mapping.key, Object.assign(Object.assign({}, this.props), onyxDataFromState));
|
|
105
115
|
this.connectMappingToOnyx(mapping, propertyName, key);
|
|
106
116
|
});
|
|
107
117
|
this.checkEvictableKeys();
|
|
108
118
|
}
|
|
109
|
-
|
|
110
119
|
componentDidUpdate(prevProps, prevState) {
|
|
111
120
|
// The whole purpose of this method is to check to see if a key that is subscribed to Onyx has changed, and then Onyx needs to be disconnected from the old
|
|
112
121
|
// key and connected to the new key.
|
|
@@ -114,13 +123,11 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
|
|
|
114
123
|
const isFirstTimeUpdatingAfterLoading = prevState.loading && !this.state.loading;
|
|
115
124
|
const onyxDataFromState = getOnyxDataFromState(this.state, mapOnyxToState);
|
|
116
125
|
const prevOnyxDataFromState = getOnyxDataFromState(prevState, mapOnyxToState);
|
|
117
|
-
|
|
118
|
-
_.each(mapOnyxToState, (mapping, propName) => {
|
|
126
|
+
underscore_1.default.each(mapOnyxToState, (mapping, propName) => {
|
|
119
127
|
// Some properties can be ignored because they aren't related to onyx keys and they will never change
|
|
120
|
-
if (
|
|
128
|
+
if (underscore_1.default.includes(mappingPropertiesToIgnoreChangesTo, propName)) {
|
|
121
129
|
return;
|
|
122
130
|
}
|
|
123
|
-
|
|
124
131
|
// The previous key comes from either:
|
|
125
132
|
// 1) The initial key that was connected to (ie. set from `componentDidMount()`)
|
|
126
133
|
// 2) The updated props which caused `componentDidUpdate()` to run
|
|
@@ -128,33 +135,31 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
|
|
|
128
135
|
// (eg. if a user switches chats really quickly). In this case, it's much more stable to always look at the changes to prevProp and prevState to derive the key.
|
|
129
136
|
// The second case cannot be used all the time because the onyx data doesn't change the first time that `componentDidUpdate()` runs after loading. In this case,
|
|
130
137
|
// the `mapping.previousKey` must be used for the comparison or else this logic never detects that onyx data could have changed during the loading process.
|
|
131
|
-
const previousKey = isFirstTimeUpdatingAfterLoading ? mapping.previousKey : Str.result(mapping.key, {
|
|
132
|
-
const newKey = Str.result(mapping.key, {
|
|
138
|
+
const previousKey = isFirstTimeUpdatingAfterLoading ? mapping.previousKey : Str.result(mapping.key, Object.assign(Object.assign({}, prevProps), prevOnyxDataFromState));
|
|
139
|
+
const newKey = Str.result(mapping.key, Object.assign(Object.assign({}, this.props), onyxDataFromState));
|
|
133
140
|
if (previousKey !== newKey) {
|
|
134
|
-
|
|
141
|
+
Onyx_1.default.disconnect(this.activeConnectionIDs[previousKey], previousKey);
|
|
135
142
|
delete this.activeConnectionIDs[previousKey];
|
|
136
143
|
this.connectMappingToOnyx(mapping, propName, newKey);
|
|
137
144
|
}
|
|
138
145
|
});
|
|
139
146
|
this.checkEvictableKeys();
|
|
140
147
|
}
|
|
141
|
-
|
|
142
148
|
componentWillUnmount() {
|
|
143
149
|
// Disconnect everything from Onyx
|
|
144
|
-
|
|
145
|
-
const key = Str.result(mapping.key, {
|
|
146
|
-
|
|
150
|
+
underscore_1.default.each(mapOnyxToState, (mapping) => {
|
|
151
|
+
const key = Str.result(mapping.key, Object.assign(Object.assign({}, this.props), getOnyxDataFromState(this.state, mapOnyxToState)));
|
|
152
|
+
Onyx_1.default.disconnect(this.activeConnectionIDs[key], key);
|
|
147
153
|
});
|
|
148
154
|
}
|
|
149
|
-
|
|
150
155
|
setStateProxy(modifier) {
|
|
151
156
|
if (this.shouldDelayUpdates) {
|
|
152
157
|
this.pendingSetStates.push(modifier);
|
|
153
|
-
}
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
154
160
|
this.setState(modifier);
|
|
155
161
|
}
|
|
156
162
|
}
|
|
157
|
-
|
|
158
163
|
/**
|
|
159
164
|
* This method is used by the internal raw Onyx `sendDataToConnection`, it is designed to prevent unnecessary renders while a component
|
|
160
165
|
* still in a "loading" (read "mounting") state. The temporary initial state is saved to the HOC instance and setState()
|
|
@@ -175,7 +180,6 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
|
|
|
175
180
|
*/
|
|
176
181
|
setWithOnyxState(statePropertyName, val) {
|
|
177
182
|
const prevValue = this.state[statePropertyName];
|
|
178
|
-
|
|
179
183
|
// If the component is not loading (read "mounting"), then we can just update the state
|
|
180
184
|
// There is a small race condition.
|
|
181
185
|
// When calling setWithOnyxState we delete the tempState object that is used to hold temporary state updates while the HOC is gathering data.
|
|
@@ -185,60 +189,48 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
|
|
|
185
189
|
// This simply bypasses the loading check if the tempState is gone and the update can be safely queued with a normal setStateProxy.
|
|
186
190
|
if (!this.state.loading || !this.tempState) {
|
|
187
191
|
// Performance optimization, do not trigger update with same values
|
|
188
|
-
if (prevValue === val ||
|
|
192
|
+
if (prevValue === val || utils_1.default.areObjectsEmpty(prevValue, val)) {
|
|
189
193
|
return;
|
|
190
194
|
}
|
|
191
|
-
|
|
192
|
-
this.setStateProxy({[statePropertyName]: val});
|
|
195
|
+
this.setStateProxy({ [statePropertyName]: val });
|
|
193
196
|
return;
|
|
194
197
|
}
|
|
195
|
-
|
|
196
198
|
this.tempState[statePropertyName] = val;
|
|
197
|
-
|
|
198
199
|
// If some key does not have a value yet, do not update the state yet
|
|
199
|
-
const tempStateIsMissingKey =
|
|
200
|
+
const tempStateIsMissingKey = underscore_1.default.some(requiredKeysForInit, (key) => underscore_1.default.isUndefined(this.tempState[key]));
|
|
200
201
|
if (tempStateIsMissingKey) {
|
|
201
202
|
return;
|
|
202
203
|
}
|
|
203
|
-
|
|
204
|
-
const stateUpdate = {...this.tempState};
|
|
204
|
+
const stateUpdate = Object.assign({}, this.tempState);
|
|
205
205
|
delete this.tempState;
|
|
206
|
-
|
|
207
206
|
// Full of hacky workarounds to prevent the race condition described above.
|
|
208
207
|
this.setState((prevState) => {
|
|
209
|
-
const finalState =
|
|
210
|
-
|
|
211
|
-
(result, value, key) => {
|
|
212
|
-
if (key === 'loading') {
|
|
213
|
-
return result;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const initialValue = mapOnyxToState[key].initialValue;
|
|
217
|
-
|
|
218
|
-
// If initialValue is there and the state contains something different it means
|
|
219
|
-
// an update has already been received and we can discard the value we are trying to hydrate
|
|
220
|
-
if (!_.isUndefined(initialValue) && !_.isUndefined(prevState[key]) && prevState[key] !== initialValue) {
|
|
221
|
-
// eslint-disable-next-line no-param-reassign
|
|
222
|
-
result[key] = prevState[key];
|
|
223
|
-
|
|
224
|
-
// if value is already there (without initial value) then we can discard the value we are trying to hydrate
|
|
225
|
-
} else if (!_.isUndefined(prevState[key])) {
|
|
226
|
-
// eslint-disable-next-line no-param-reassign
|
|
227
|
-
result[key] = prevState[key];
|
|
228
|
-
} else {
|
|
229
|
-
// eslint-disable-next-line no-param-reassign
|
|
230
|
-
result[key] = value;
|
|
231
|
-
}
|
|
208
|
+
const finalState = underscore_1.default.reduce(stateUpdate, (result, value, key) => {
|
|
209
|
+
if (key === 'loading') {
|
|
232
210
|
return result;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
211
|
+
}
|
|
212
|
+
const initialValue = mapOnyxToState[key].initialValue;
|
|
213
|
+
// If initialValue is there and the state contains something different it means
|
|
214
|
+
// an update has already been received and we can discard the value we are trying to hydrate
|
|
215
|
+
if (!underscore_1.default.isUndefined(initialValue) && !underscore_1.default.isUndefined(prevState[key]) && prevState[key] !== initialValue) {
|
|
216
|
+
// eslint-disable-next-line no-param-reassign
|
|
217
|
+
result[key] = prevState[key];
|
|
218
|
+
// if value is already there (without initial value) then we can discard the value we are trying to hydrate
|
|
219
|
+
}
|
|
220
|
+
else if (!underscore_1.default.isUndefined(prevState[key])) {
|
|
221
|
+
// eslint-disable-next-line no-param-reassign
|
|
222
|
+
result[key] = prevState[key];
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
// eslint-disable-next-line no-param-reassign
|
|
226
|
+
result[key] = value;
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}, {});
|
|
237
230
|
finalState.loading = false;
|
|
238
231
|
return finalState;
|
|
239
232
|
});
|
|
240
233
|
}
|
|
241
|
-
|
|
242
234
|
/**
|
|
243
235
|
* Makes sure each Onyx key we requested has been set to state with a value of some kind.
|
|
244
236
|
* We are doing this so that the wrapped component will only render when all the data
|
|
@@ -248,26 +240,23 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
|
|
|
248
240
|
// We will add this key to our list of recently accessed keys
|
|
249
241
|
// if the canEvict function returns true. This is necessary criteria
|
|
250
242
|
// we MUST use to specify if a key can be removed or not.
|
|
251
|
-
|
|
252
|
-
if (
|
|
243
|
+
underscore_1.default.each(mapOnyxToState, (mapping) => {
|
|
244
|
+
if (underscore_1.default.isUndefined(mapping.canEvict)) {
|
|
253
245
|
return;
|
|
254
246
|
}
|
|
255
|
-
|
|
256
247
|
const canEvict = Str.result(mapping.canEvict, this.props);
|
|
257
248
|
const key = Str.result(mapping.key, this.props);
|
|
258
|
-
|
|
259
|
-
if (!Onyx.isSafeEvictionKey(key)) {
|
|
249
|
+
if (!Onyx_1.default.isSafeEvictionKey(key)) {
|
|
260
250
|
throw new Error(`canEvict can't be used on key '${key}'. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({safeEvictionKeys: []}).`);
|
|
261
251
|
}
|
|
262
|
-
|
|
263
252
|
if (canEvict) {
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
|
|
253
|
+
Onyx_1.default.removeFromEvictionBlockList(key, mapping.connectionID);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
Onyx_1.default.addToEvictionBlockList(key, mapping.connectionID);
|
|
267
257
|
}
|
|
268
258
|
});
|
|
269
259
|
}
|
|
270
|
-
|
|
271
260
|
/**
|
|
272
261
|
* Takes a single mapping and binds the state of the component to the store
|
|
273
262
|
*
|
|
@@ -284,77 +273,51 @@ export default function (mapOnyxToState, shouldDelayUpdates = false) {
|
|
|
284
273
|
// dependent keys to finish loading their data.
|
|
285
274
|
// eslint-disable-next-line no-param-reassign
|
|
286
275
|
mapOnyxToState[statePropertyName].previousKey = key;
|
|
287
|
-
|
|
288
276
|
// eslint-disable-next-line rulesdir/prefer-onyx-connect-in-libs
|
|
289
|
-
this.activeConnectionIDs[key] =
|
|
290
|
-
|
|
291
|
-
key,
|
|
292
|
-
statePropertyName,
|
|
293
|
-
withOnyxInstance: this,
|
|
294
|
-
displayName,
|
|
295
|
-
});
|
|
277
|
+
this.activeConnectionIDs[key] = Onyx_1.default.connect(Object.assign(Object.assign({}, mapping), { key,
|
|
278
|
+
statePropertyName, withOnyxInstance: this, displayName }));
|
|
296
279
|
}
|
|
297
|
-
|
|
298
280
|
flushPendingSetStates() {
|
|
299
281
|
if (!this.shouldDelayUpdates) {
|
|
300
282
|
return;
|
|
301
283
|
}
|
|
302
|
-
|
|
303
284
|
this.shouldDelayUpdates = false;
|
|
304
|
-
|
|
305
285
|
this.pendingSetStates.forEach((modifier) => {
|
|
306
286
|
this.setState(modifier);
|
|
307
287
|
});
|
|
308
288
|
this.pendingSetStates = [];
|
|
309
289
|
}
|
|
310
|
-
|
|
311
290
|
render() {
|
|
312
291
|
// Remove any null values so that React replaces them with default props
|
|
313
|
-
const propsToPass =
|
|
314
|
-
|
|
292
|
+
const propsToPass = underscore_1.default.omit(this.props, underscore_1.default.isNull);
|
|
315
293
|
if (this.state.loading) {
|
|
316
294
|
return null;
|
|
317
295
|
}
|
|
318
|
-
|
|
319
296
|
// Remove any internal state properties used by withOnyx
|
|
320
297
|
// that should not be passed to a wrapped component
|
|
321
|
-
let stateToPass =
|
|
322
|
-
stateToPass =
|
|
323
|
-
|
|
298
|
+
let stateToPass = underscore_1.default.omit(this.state, 'loading');
|
|
299
|
+
stateToPass = underscore_1.default.omit(stateToPass, underscore_1.default.isNull);
|
|
324
300
|
// Spreading props and state is necessary in an HOC where the data cannot be predicted
|
|
325
|
-
return (
|
|
326
|
-
<WrappedComponent
|
|
327
|
-
markReadyForHydration={this.flushPendingSetStates}
|
|
328
|
-
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
329
|
-
{...propsToPass}
|
|
330
|
-
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
331
|
-
{...stateToPass}
|
|
332
|
-
ref={this.props.forwardedRef}
|
|
333
|
-
/>
|
|
334
|
-
);
|
|
301
|
+
return (react_1.default.createElement(WrappedComponent, Object.assign({ markReadyForHydration: this.flushPendingSetStates }, propsToPass, stateToPass, { ref: this.props.forwardedRef })));
|
|
335
302
|
}
|
|
336
303
|
}
|
|
337
|
-
|
|
338
304
|
withOnyx.propTypes = {
|
|
339
|
-
forwardedRef:
|
|
340
|
-
|
|
305
|
+
forwardedRef: prop_types_1.default.oneOfType([
|
|
306
|
+
prop_types_1.default.func,
|
|
341
307
|
// eslint-disable-next-line react/forbid-prop-types
|
|
342
|
-
|
|
308
|
+
prop_types_1.default.shape({ current: prop_types_1.default.object }),
|
|
343
309
|
]),
|
|
344
310
|
};
|
|
345
311
|
withOnyx.defaultProps = {
|
|
346
312
|
forwardedRef: undefined,
|
|
347
313
|
};
|
|
348
314
|
withOnyx.displayName = `withOnyx(${displayName})`;
|
|
349
|
-
return
|
|
315
|
+
return react_1.default.forwardRef((props, ref) => {
|
|
350
316
|
const Component = withOnyx;
|
|
351
|
-
return (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
{...props}
|
|
355
|
-
forwardedRef={ref}
|
|
356
|
-
/>
|
|
357
|
-
);
|
|
317
|
+
return (react_1.default.createElement(Component
|
|
318
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
319
|
+
, Object.assign({}, props, { forwardedRef: ref })));
|
|
358
320
|
});
|
|
359
321
|
};
|
|
360
322
|
}
|
|
323
|
+
exports.default = default_1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-onyx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"author": "Expensify, Inc.",
|
|
5
5
|
"homepage": "https://expensify.com",
|
|
6
6
|
"description": "State management for React Native",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"keywords": [
|
|
10
10
|
"React Native",
|
|
11
11
|
"React",
|
|
12
|
-
"
|
|
12
|
+
"Persistent storage",
|
|
13
13
|
"Pub/Sub"
|
|
14
14
|
],
|
|
15
15
|
"repository": {
|
|
@@ -21,24 +21,20 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist/**/*",
|
|
24
|
-
"lib/**/*",
|
|
25
|
-
"native.js",
|
|
26
|
-
"web.js",
|
|
27
24
|
"API.md",
|
|
28
25
|
"README.md",
|
|
29
26
|
"LICENSE.md"
|
|
30
27
|
],
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"browser": "web.js",
|
|
34
|
-
"types": "lib/index.d.ts",
|
|
28
|
+
"main": "dist/index.js",
|
|
29
|
+
"types": "dist/index.d.ts",
|
|
35
30
|
"scripts": {
|
|
36
|
-
"build": "webpack --config webpack.config.js",
|
|
37
|
-
"build:docs": "node buildDocs.js",
|
|
38
31
|
"lint": "eslint .",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"test": "jest",
|
|
34
|
+
"build": "tsc -p tsconfig.build.json && cp ./lib/*.d.ts ./dist",
|
|
35
|
+
"build:docs": "node buildDocs.js",
|
|
39
36
|
"lint-tests": "eslint tests/**",
|
|
40
|
-
"prettier": "prettier --write ."
|
|
41
|
-
"test": "jest"
|
|
37
|
+
"prettier": "prettier --write ."
|
|
42
38
|
},
|
|
43
39
|
"dependencies": {
|
|
44
40
|
"ascii-table": "0.0.9",
|
|
@@ -46,27 +42,29 @@
|
|
|
46
42
|
"underscore": "^1.13.6"
|
|
47
43
|
},
|
|
48
44
|
"devDependencies": {
|
|
49
|
-
"@
|
|
50
|
-
"@
|
|
51
|
-
"@
|
|
52
|
-
"@react-native-community/eslint-config": "^2.0.0",
|
|
45
|
+
"@lwc/eslint-plugin-lwc": "^1.7.2",
|
|
46
|
+
"@react-native-community/eslint-config": "^3.2.0",
|
|
47
|
+
"@react-native/polyfills": "^2.0.0",
|
|
53
48
|
"@testing-library/jest-native": "^3.4.2",
|
|
54
49
|
"@testing-library/react-native": "^7.0.2",
|
|
50
|
+
"@types/jest": "^28.1.8",
|
|
55
51
|
"@types/node": "^20.11.5",
|
|
56
52
|
"@types/react": "^18.2.14",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"eslint": "^
|
|
61
|
-
"eslint
|
|
53
|
+
"@types/react-dom": "^18.2.18",
|
|
54
|
+
"@types/react-native": "^0.70.0",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
|
56
|
+
"@typescript-eslint/parser": "^6.19.0",
|
|
57
|
+
"eslint": "^8.56.0",
|
|
58
|
+
"eslint-config-expensify": "^2.0.43",
|
|
62
59
|
"eslint-config-prettier": "^8.8.0",
|
|
63
|
-
"eslint-plugin-
|
|
60
|
+
"eslint-plugin-import": "^2.29.1",
|
|
61
|
+
"eslint-plugin-jsx-a11y": "^6.8.0",
|
|
64
62
|
"eslint-plugin-react": "^7.31.10",
|
|
65
63
|
"idb-keyval": "^6.2.1",
|
|
66
64
|
"jest": "^26.5.2",
|
|
67
65
|
"jest-cli": "^26.5.2",
|
|
68
66
|
"jsdoc-to-markdown": "^7.1.0",
|
|
69
|
-
"metro-react-native-babel-preset": "^0.
|
|
67
|
+
"metro-react-native-babel-preset": "^0.77.0",
|
|
70
68
|
"prettier": "^2.8.8",
|
|
71
69
|
"prop-types": "^15.7.2",
|
|
72
70
|
"react": "18.2.0",
|
|
@@ -77,9 +75,7 @@
|
|
|
77
75
|
"react-native-quick-sqlite": "^8.0.6",
|
|
78
76
|
"react-test-renderer": "18.1.0",
|
|
79
77
|
"type-fest": "^3.12.0",
|
|
80
|
-
"
|
|
81
|
-
"webpack-cli": "^4.9.2",
|
|
82
|
-
"webpack-merge": "^5.8.0"
|
|
78
|
+
"typescript": "^5.3.3"
|
|
83
79
|
},
|
|
84
80
|
"peerDependencies": {
|
|
85
81
|
"idb-keyval": "^6.2.1",
|
|
@@ -107,32 +103,5 @@
|
|
|
107
103
|
"node": ">=20.10.0",
|
|
108
104
|
"npm": ">=10.2.3"
|
|
109
105
|
},
|
|
110
|
-
"jest": {
|
|
111
|
-
"preset": "react-native",
|
|
112
|
-
"transform": {
|
|
113
|
-
"^.+\\.jsx?$": "babel-jest"
|
|
114
|
-
},
|
|
115
|
-
"transformIgnorePatterns": [
|
|
116
|
-
"node_modules/(?!react-native)/"
|
|
117
|
-
],
|
|
118
|
-
"testPathIgnorePatterns": [
|
|
119
|
-
"<rootDir>/node_modules/",
|
|
120
|
-
"<rootDir>/tests/unit/mocks/"
|
|
121
|
-
],
|
|
122
|
-
"testMatch": [
|
|
123
|
-
"**/tests/unit/**/*.[jt]s?(x)",
|
|
124
|
-
"**/?(*.)+(spec|test).[jt]s?(x)"
|
|
125
|
-
],
|
|
126
|
-
"globals": {
|
|
127
|
-
"__DEV__": true,
|
|
128
|
-
"WebSocket": {}
|
|
129
|
-
},
|
|
130
|
-
"timers": "fake",
|
|
131
|
-
"testEnvironment": "jsdom",
|
|
132
|
-
"setupFilesAfterEnv": [
|
|
133
|
-
"@testing-library/jest-native/extend-expect",
|
|
134
|
-
"./jestSetup.js"
|
|
135
|
-
]
|
|
136
|
-
},
|
|
137
106
|
"sideEffects": false
|
|
138
107
|
}
|