@ninetailed/experience.js-react 7.12.1 → 7.13.0-beta.1
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/index.cjs.js +33 -24
- package/index.esm.js +35 -24
- package/package.json +4 -4
package/index.cjs.js
CHANGED
|
@@ -100,7 +100,6 @@ function __rest(s, e) {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
function formatProfileForHook(profile) {
|
|
103
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
104
103
|
const profileStateWithoutExperiences = __rest(profile, ["experiences"]);
|
|
105
104
|
return Object.assign(Object.assign({}, profileStateWithoutExperiences), {
|
|
106
105
|
loading: profile.status === 'loading'
|
|
@@ -162,29 +161,36 @@ const usePersonalize = (baseline, variants, options = {
|
|
|
162
161
|
function useFlag(flagKey, defaultValue) {
|
|
163
162
|
const ninetailed = useNinetailed();
|
|
164
163
|
const lastProcessedState = React.useRef(null);
|
|
164
|
+
const defaultValueRef = React.useRef(defaultValue);
|
|
165
|
+
const flagKeyRef = React.useRef(flagKey);
|
|
165
166
|
const [result, setResult] = React.useState({
|
|
166
167
|
value: defaultValue,
|
|
167
168
|
status: 'loading',
|
|
168
169
|
error: null
|
|
169
170
|
});
|
|
171
|
+
// Effect 1: Track changes to `flagKey` or `defaultValue`
|
|
172
|
+
React.useEffect(() => {
|
|
173
|
+
if (!radash.isEqual(defaultValueRef.current, defaultValue) || flagKeyRef.current !== flagKey) {
|
|
174
|
+
defaultValueRef.current = defaultValue;
|
|
175
|
+
flagKeyRef.current = flagKey;
|
|
176
|
+
setResult({
|
|
177
|
+
value: defaultValue,
|
|
178
|
+
status: 'loading',
|
|
179
|
+
error: null
|
|
180
|
+
});
|
|
181
|
+
lastProcessedState.current = null;
|
|
182
|
+
}
|
|
183
|
+
}, [flagKey, defaultValue]);
|
|
184
|
+
// Effect 2: Handle Ninetailed changes
|
|
170
185
|
React.useEffect(() => {
|
|
171
|
-
// Reset state when dependencies change
|
|
172
|
-
setResult({
|
|
173
|
-
value: defaultValue,
|
|
174
|
-
status: 'loading',
|
|
175
|
-
error: null
|
|
176
|
-
});
|
|
177
|
-
lastProcessedState.current = null;
|
|
178
186
|
const unsubscribe = ninetailed.onChangesChange(changesState => {
|
|
179
187
|
if (lastProcessedState.current && radash.isEqual(lastProcessedState.current, changesState)) {
|
|
180
|
-
experience_jsShared.logger.debug('Change State Did Not Change', changesState);
|
|
181
188
|
return;
|
|
182
189
|
}
|
|
183
190
|
lastProcessedState.current = changesState;
|
|
184
191
|
if (changesState.status === 'loading') {
|
|
185
|
-
// Don't use a function updater here to avoid type issues
|
|
186
192
|
setResult({
|
|
187
|
-
value:
|
|
193
|
+
value: defaultValueRef.current,
|
|
188
194
|
status: 'loading',
|
|
189
195
|
error: null
|
|
190
196
|
});
|
|
@@ -192,40 +198,37 @@ function useFlag(flagKey, defaultValue) {
|
|
|
192
198
|
}
|
|
193
199
|
if (changesState.status === 'error') {
|
|
194
200
|
setResult({
|
|
195
|
-
value:
|
|
201
|
+
value: defaultValueRef.current,
|
|
196
202
|
status: 'error',
|
|
197
203
|
error: changesState.error
|
|
198
204
|
});
|
|
199
205
|
return;
|
|
200
206
|
}
|
|
201
207
|
try {
|
|
202
|
-
|
|
203
|
-
const change = changesState.changes.find(change => change.key === flagKey);
|
|
208
|
+
const change = changesState.changes.find(change => change.key === flagKeyRef.current);
|
|
204
209
|
if (change && change.type === experience_jsShared.ChangeTypes.Variable) {
|
|
205
|
-
const flagValue = change.value;
|
|
206
210
|
setResult({
|
|
207
|
-
value:
|
|
211
|
+
value: change.value,
|
|
208
212
|
status: 'success',
|
|
209
213
|
error: null
|
|
210
214
|
});
|
|
211
215
|
} else {
|
|
212
|
-
// Flag not found or wrong type, use default
|
|
213
216
|
setResult({
|
|
214
|
-
value:
|
|
217
|
+
value: defaultValueRef.current,
|
|
215
218
|
status: 'success',
|
|
216
219
|
error: null
|
|
217
220
|
});
|
|
218
221
|
}
|
|
219
222
|
} catch (error) {
|
|
220
223
|
setResult({
|
|
221
|
-
value:
|
|
224
|
+
value: defaultValueRef.current,
|
|
222
225
|
status: 'error',
|
|
223
226
|
error: error instanceof Error ? error : new Error(String(error))
|
|
224
227
|
});
|
|
225
228
|
}
|
|
226
229
|
});
|
|
227
230
|
return unsubscribe;
|
|
228
|
-
}, [ninetailed
|
|
231
|
+
}, [ninetailed]);
|
|
229
232
|
return result;
|
|
230
233
|
}
|
|
231
234
|
|
|
@@ -531,9 +534,7 @@ const Experience = _a => {
|
|
|
531
534
|
const componentElement = componentRef.current;
|
|
532
535
|
if (componentElement && !(componentElement instanceof Element)) {
|
|
533
536
|
const isObject = typeof componentElement === 'object' && componentElement !== null;
|
|
534
|
-
const constructorName = isObject ?
|
|
535
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
536
|
-
componentElement.constructor.name : '';
|
|
537
|
+
const constructorName = isObject ? componentElement.constructor.name : '';
|
|
537
538
|
const isConstructorNameNotObject = constructorName && constructorName !== 'Object';
|
|
538
539
|
logger.warn(`The component ref being in Experience is an invalid element. Expected an Element but got ${typeof componentElement}${isConstructorNameNotObject ? ` of type ${constructorName}` : ''}. This component won't be observed.`);
|
|
539
540
|
return () => {
|
|
@@ -644,7 +645,15 @@ const ESRLoadingComponent = _a => {
|
|
|
644
645
|
}
|
|
645
646
|
}));
|
|
646
647
|
}
|
|
647
|
-
const component = experience.components.find(component =>
|
|
648
|
+
const component = experience.components.find(component => {
|
|
649
|
+
if (!('id' in component.baseline)) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
if (!('id' in baseline)) {
|
|
653
|
+
return component.baseline.id === undefined;
|
|
654
|
+
}
|
|
655
|
+
return component.baseline.id === baseline.id;
|
|
656
|
+
});
|
|
648
657
|
if (!component) {
|
|
649
658
|
return jsxRuntime.jsx(Component, Object.assign({}, passthroughProps, baseline, {
|
|
650
659
|
ninetailed: {
|
package/index.esm.js
CHANGED
|
@@ -78,7 +78,6 @@ function _objectWithoutPropertiesLoose(source, excluded) {
|
|
|
78
78
|
|
|
79
79
|
const _excluded$3 = ["experiences"];
|
|
80
80
|
function formatProfileForHook(profile) {
|
|
81
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
82
81
|
const profileStateWithoutExperiences = _objectWithoutPropertiesLoose(profile, _excluded$3);
|
|
83
82
|
return Object.assign({}, profileStateWithoutExperiences, {
|
|
84
83
|
loading: profile.status === 'loading'
|
|
@@ -143,29 +142,38 @@ const usePersonalize = (baseline, variants, options = {
|
|
|
143
142
|
function useFlag(flagKey, defaultValue) {
|
|
144
143
|
const ninetailed = useNinetailed();
|
|
145
144
|
const lastProcessedState = useRef(null);
|
|
145
|
+
const defaultValueRef = useRef(defaultValue);
|
|
146
|
+
const flagKeyRef = useRef(flagKey);
|
|
146
147
|
const [result, setResult] = useState({
|
|
147
148
|
value: defaultValue,
|
|
148
149
|
status: 'loading',
|
|
149
150
|
error: null
|
|
150
151
|
});
|
|
152
|
+
|
|
153
|
+
// Effect 1: Track changes to `flagKey` or `defaultValue`
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
if (!isEqual(defaultValueRef.current, defaultValue) || flagKeyRef.current !== flagKey) {
|
|
156
|
+
defaultValueRef.current = defaultValue;
|
|
157
|
+
flagKeyRef.current = flagKey;
|
|
158
|
+
setResult({
|
|
159
|
+
value: defaultValue,
|
|
160
|
+
status: 'loading',
|
|
161
|
+
error: null
|
|
162
|
+
});
|
|
163
|
+
lastProcessedState.current = null;
|
|
164
|
+
}
|
|
165
|
+
}, [flagKey, defaultValue]);
|
|
166
|
+
|
|
167
|
+
// Effect 2: Handle Ninetailed changes
|
|
151
168
|
useEffect(() => {
|
|
152
|
-
// Reset state when dependencies change
|
|
153
|
-
setResult({
|
|
154
|
-
value: defaultValue,
|
|
155
|
-
status: 'loading',
|
|
156
|
-
error: null
|
|
157
|
-
});
|
|
158
|
-
lastProcessedState.current = null;
|
|
159
169
|
const unsubscribe = ninetailed.onChangesChange(changesState => {
|
|
160
170
|
if (lastProcessedState.current && isEqual(lastProcessedState.current, changesState)) {
|
|
161
|
-
logger.debug('Change State Did Not Change', changesState);
|
|
162
171
|
return;
|
|
163
172
|
}
|
|
164
173
|
lastProcessedState.current = changesState;
|
|
165
174
|
if (changesState.status === 'loading') {
|
|
166
|
-
// Don't use a function updater here to avoid type issues
|
|
167
175
|
setResult({
|
|
168
|
-
value:
|
|
176
|
+
value: defaultValueRef.current,
|
|
169
177
|
status: 'loading',
|
|
170
178
|
error: null
|
|
171
179
|
});
|
|
@@ -173,40 +181,37 @@ function useFlag(flagKey, defaultValue) {
|
|
|
173
181
|
}
|
|
174
182
|
if (changesState.status === 'error') {
|
|
175
183
|
setResult({
|
|
176
|
-
value:
|
|
184
|
+
value: defaultValueRef.current,
|
|
177
185
|
status: 'error',
|
|
178
186
|
error: changesState.error
|
|
179
187
|
});
|
|
180
188
|
return;
|
|
181
189
|
}
|
|
182
190
|
try {
|
|
183
|
-
|
|
184
|
-
const change = changesState.changes.find(change => change.key === flagKey);
|
|
191
|
+
const change = changesState.changes.find(change => change.key === flagKeyRef.current);
|
|
185
192
|
if (change && change.type === ChangeTypes.Variable) {
|
|
186
|
-
const flagValue = change.value;
|
|
187
193
|
setResult({
|
|
188
|
-
value:
|
|
194
|
+
value: change.value,
|
|
189
195
|
status: 'success',
|
|
190
196
|
error: null
|
|
191
197
|
});
|
|
192
198
|
} else {
|
|
193
|
-
// Flag not found or wrong type, use default
|
|
194
199
|
setResult({
|
|
195
|
-
value:
|
|
200
|
+
value: defaultValueRef.current,
|
|
196
201
|
status: 'success',
|
|
197
202
|
error: null
|
|
198
203
|
});
|
|
199
204
|
}
|
|
200
205
|
} catch (error) {
|
|
201
206
|
setResult({
|
|
202
|
-
value:
|
|
207
|
+
value: defaultValueRef.current,
|
|
203
208
|
status: 'error',
|
|
204
209
|
error: error instanceof Error ? error : new Error(String(error))
|
|
205
210
|
});
|
|
206
211
|
}
|
|
207
212
|
});
|
|
208
213
|
return unsubscribe;
|
|
209
|
-
}, [ninetailed
|
|
214
|
+
}, [ninetailed]);
|
|
210
215
|
return result;
|
|
211
216
|
}
|
|
212
217
|
|
|
@@ -515,9 +520,7 @@ const Experience = _ref2 => {
|
|
|
515
520
|
const componentElement = componentRef.current;
|
|
516
521
|
if (componentElement && !(componentElement instanceof Element)) {
|
|
517
522
|
const isObject = typeof componentElement === 'object' && componentElement !== null;
|
|
518
|
-
const constructorName = isObject ?
|
|
519
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
520
|
-
componentElement.constructor.name : '';
|
|
523
|
+
const constructorName = isObject ? componentElement.constructor.name : '';
|
|
521
524
|
const isConstructorNameNotObject = constructorName && constructorName !== 'Object';
|
|
522
525
|
logger.warn(`The component ref being in Experience is an invalid element. Expected an Element but got ${typeof componentElement}${isConstructorNameNotObject ? ` of type ${constructorName}` : ''}. This component won't be observed.`);
|
|
523
526
|
return () => {
|
|
@@ -628,7 +631,15 @@ const ESRLoadingComponent = _ref => {
|
|
|
628
631
|
}
|
|
629
632
|
}));
|
|
630
633
|
}
|
|
631
|
-
const component = experience.components.find(component =>
|
|
634
|
+
const component = experience.components.find(component => {
|
|
635
|
+
if (!('id' in component.baseline)) {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
if (!('id' in baseline)) {
|
|
639
|
+
return component.baseline.id === undefined;
|
|
640
|
+
}
|
|
641
|
+
return component.baseline.id === baseline.id;
|
|
642
|
+
});
|
|
632
643
|
if (!component) {
|
|
633
644
|
return /*#__PURE__*/jsx(Component, Object.assign({}, passthroughProps, baseline, {
|
|
634
645
|
ninetailed: {
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ninetailed/experience.js-react",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.13.0-beta.1",
|
|
4
4
|
"description": "Ninetailed SDK for React",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@ninetailed/experience.js": "7.
|
|
7
|
-
"@ninetailed/experience.js-shared": "7.
|
|
8
|
-
"@ninetailed/experience.js-plugin-analytics": "7.
|
|
6
|
+
"@ninetailed/experience.js": "7.13.0-beta.1",
|
|
7
|
+
"@ninetailed/experience.js-shared": "7.13.0-beta.1",
|
|
8
|
+
"@ninetailed/experience.js-plugin-analytics": "7.13.0-beta.1",
|
|
9
9
|
"radash": "10.9.0",
|
|
10
10
|
"react-is": "18.2.0"
|
|
11
11
|
},
|