@ninetailed/experience.js-react 7.11.0 → 7.11.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 +38 -21
- package/index.esm.js +40 -21
- package/package.json +4 -4
- package/src/lib/useProfile.d.ts +15 -51
package/index.cjs.js
CHANGED
|
@@ -99,32 +99,49 @@ function __rest(s, e) {
|
|
|
99
99
|
return t;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
function formatProfileForHook(profile) {
|
|
103
|
+
const profileStateWithoutExperiences = __rest(profile, ["experiences"]);
|
|
104
|
+
return Object.assign(Object.assign({}, profileStateWithoutExperiences), {
|
|
105
|
+
loading: profile.status === 'loading'
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Custom hook that provides access to the Ninetailed profile state
|
|
110
|
+
* with the 'experiences' property removed to prevent unnecessary re-renders.
|
|
111
|
+
*
|
|
112
|
+
* This hook handles profile state changes efficiently by:
|
|
113
|
+
* 1. Only updating state when actual changes occur
|
|
114
|
+
* 2. Removing the large 'experiences' object from the state
|
|
115
|
+
* 3. Properly cleaning up subscriptions when components unmount
|
|
116
|
+
*
|
|
117
|
+
* @returns The profile state without the 'experiences' property
|
|
118
|
+
*/
|
|
102
119
|
const useProfile = () => {
|
|
103
120
|
const ninetailed = useNinetailed();
|
|
104
|
-
const [
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
* This effect compares the old and new profile state before updating it.
|
|
108
|
-
* We use a ref to avoid an infinite loop which can happen when an empty profile state was updated with no changes.
|
|
109
|
-
* This behaviour occurred as the validation handling on the error property was not set properly in the "CreateProfile" and "UpdateProfile" endpoint types.
|
|
110
|
-
* Furthermore, it was also observed, that it "only" occurred when the preview plugin was used in parallel.
|
|
111
|
-
*/
|
|
121
|
+
const [strippedProfileState, setStrippedProfileState] = React.useState(formatProfileForHook(ninetailed.profileState));
|
|
122
|
+
// Reference to track the previous profile state for comparison
|
|
123
|
+
const profileStateRef = React.useRef(ninetailed.profileState);
|
|
112
124
|
React.useEffect(() => {
|
|
113
|
-
ninetailed.onProfileChange(
|
|
114
|
-
if
|
|
115
|
-
|
|
125
|
+
const unsubscribe = ninetailed.onProfileChange(changedProfileState => {
|
|
126
|
+
// Skip update if the profile hasn't actually changed
|
|
127
|
+
// Here we compare the entire profile including experiences and changes
|
|
128
|
+
if (radash.isEqual(changedProfileState, profileStateRef.current)) {
|
|
129
|
+
experience_jsShared.logger.debug('Profile State Did Not Change', changedProfileState);
|
|
116
130
|
return;
|
|
117
|
-
} else {
|
|
118
|
-
setProfileState(profileState);
|
|
119
|
-
profileStateRef.current = profileState;
|
|
120
|
-
experience_jsShared.logger.debug('Profile State Changed', profileState);
|
|
121
131
|
}
|
|
132
|
+
profileStateRef.current = changedProfileState;
|
|
133
|
+
experience_jsShared.logger.debug('Profile State Changed', changedProfileState);
|
|
134
|
+
setStrippedProfileState(formatProfileForHook(changedProfileState));
|
|
122
135
|
});
|
|
136
|
+
// Clean up subscription when component unmounts
|
|
137
|
+
return () => {
|
|
138
|
+
if (typeof unsubscribe === 'function') {
|
|
139
|
+
unsubscribe();
|
|
140
|
+
experience_jsShared.logger.debug('Unsubscribed from profile state changes');
|
|
141
|
+
}
|
|
142
|
+
};
|
|
123
143
|
}, []);
|
|
124
|
-
|
|
125
|
-
return Object.assign(Object.assign({}, profileStateWithoutExperiences), {
|
|
126
|
-
loading: profileState.status === 'loading'
|
|
127
|
-
});
|
|
144
|
+
return strippedProfileState;
|
|
128
145
|
};
|
|
129
146
|
|
|
130
147
|
const usePersonalize = (baseline, variants, options = {
|
|
@@ -253,8 +270,8 @@ const MergeTag = ({
|
|
|
253
270
|
fallback
|
|
254
271
|
}) => {
|
|
255
272
|
const {
|
|
256
|
-
|
|
257
|
-
|
|
273
|
+
profile,
|
|
274
|
+
loading
|
|
258
275
|
} = useProfile();
|
|
259
276
|
if (loading || !profile) {
|
|
260
277
|
return null;
|
package/index.esm.js
CHANGED
|
@@ -77,33 +77,52 @@ function _objectWithoutPropertiesLoose(source, excluded) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
const _excluded$3 = ["experiences"];
|
|
80
|
+
function formatProfileForHook(profile) {
|
|
81
|
+
const profileStateWithoutExperiences = _objectWithoutPropertiesLoose(profile, _excluded$3);
|
|
82
|
+
return Object.assign({}, profileStateWithoutExperiences, {
|
|
83
|
+
loading: profile.status === 'loading'
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Custom hook that provides access to the Ninetailed profile state
|
|
89
|
+
* with the 'experiences' property removed to prevent unnecessary re-renders.
|
|
90
|
+
*
|
|
91
|
+
* This hook handles profile state changes efficiently by:
|
|
92
|
+
* 1. Only updating state when actual changes occur
|
|
93
|
+
* 2. Removing the large 'experiences' object from the state
|
|
94
|
+
* 3. Properly cleaning up subscriptions when components unmount
|
|
95
|
+
*
|
|
96
|
+
* @returns The profile state without the 'experiences' property
|
|
97
|
+
*/
|
|
80
98
|
const useProfile = () => {
|
|
81
99
|
const ninetailed = useNinetailed();
|
|
82
|
-
const [
|
|
83
|
-
const profileStateRef = useRef({});
|
|
100
|
+
const [strippedProfileState, setStrippedProfileState] = useState(formatProfileForHook(ninetailed.profileState));
|
|
84
101
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
* We use a ref to avoid an infinite loop which can happen when an empty profile state was updated with no changes.
|
|
88
|
-
* This behaviour occurred as the validation handling on the error property was not set properly in the "CreateProfile" and "UpdateProfile" endpoint types.
|
|
89
|
-
* Furthermore, it was also observed, that it "only" occurred when the preview plugin was used in parallel.
|
|
90
|
-
*/
|
|
102
|
+
// Reference to track the previous profile state for comparison
|
|
103
|
+
const profileStateRef = useRef(ninetailed.profileState);
|
|
91
104
|
useEffect(() => {
|
|
92
|
-
ninetailed.onProfileChange(
|
|
93
|
-
if
|
|
94
|
-
|
|
105
|
+
const unsubscribe = ninetailed.onProfileChange(changedProfileState => {
|
|
106
|
+
// Skip update if the profile hasn't actually changed
|
|
107
|
+
// Here we compare the entire profile including experiences and changes
|
|
108
|
+
if (isEqual(changedProfileState, profileStateRef.current)) {
|
|
109
|
+
logger.debug('Profile State Did Not Change', changedProfileState);
|
|
95
110
|
return;
|
|
96
|
-
} else {
|
|
97
|
-
setProfileState(profileState);
|
|
98
|
-
profileStateRef.current = profileState;
|
|
99
|
-
logger.debug('Profile State Changed', profileState);
|
|
100
111
|
}
|
|
112
|
+
profileStateRef.current = changedProfileState;
|
|
113
|
+
logger.debug('Profile State Changed', changedProfileState);
|
|
114
|
+
setStrippedProfileState(formatProfileForHook(changedProfileState));
|
|
101
115
|
});
|
|
116
|
+
|
|
117
|
+
// Clean up subscription when component unmounts
|
|
118
|
+
return () => {
|
|
119
|
+
if (typeof unsubscribe === 'function') {
|
|
120
|
+
unsubscribe();
|
|
121
|
+
logger.debug('Unsubscribed from profile state changes');
|
|
122
|
+
}
|
|
123
|
+
};
|
|
102
124
|
}, []);
|
|
103
|
-
|
|
104
|
-
return Object.assign({}, profileStateWithoutExperiences, {
|
|
105
|
-
loading: profileState.status === 'loading'
|
|
106
|
-
});
|
|
125
|
+
return strippedProfileState;
|
|
107
126
|
};
|
|
108
127
|
|
|
109
128
|
const usePersonalize = (baseline, variants, options = {
|
|
@@ -232,8 +251,8 @@ const MergeTag = ({
|
|
|
232
251
|
fallback
|
|
233
252
|
}) => {
|
|
234
253
|
const {
|
|
235
|
-
|
|
236
|
-
|
|
254
|
+
profile,
|
|
255
|
+
loading
|
|
237
256
|
} = useProfile();
|
|
238
257
|
if (loading || !profile) {
|
|
239
258
|
return null;
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ninetailed/experience.js-react",
|
|
3
|
-
"version": "7.11.
|
|
3
|
+
"version": "7.11.1",
|
|
4
4
|
"description": "Ninetailed SDK for React",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@ninetailed/experience.js": "7.11.
|
|
7
|
-
"@ninetailed/experience.js-shared": "7.11.
|
|
8
|
-
"@ninetailed/experience.js-plugin-analytics": "7.11.
|
|
6
|
+
"@ninetailed/experience.js": "7.11.1",
|
|
7
|
+
"@ninetailed/experience.js-shared": "7.11.1",
|
|
8
|
+
"@ninetailed/experience.js-plugin-analytics": "7.11.1",
|
|
9
9
|
"radash": "10.9.0",
|
|
10
10
|
"react-is": "18.2.0"
|
|
11
11
|
},
|
package/src/lib/useProfile.d.ts
CHANGED
|
@@ -1,53 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { ProfileState } from '@ninetailed/experience.js';
|
|
2
|
+
type UseProfileHookResult = Omit<ProfileState, 'experiences'> & {
|
|
2
3
|
loading: boolean;
|
|
3
|
-
from: "api" | "hydrated";
|
|
4
|
-
status: "loading";
|
|
5
|
-
profile: null;
|
|
6
|
-
error: null;
|
|
7
|
-
} | {
|
|
8
|
-
loading: boolean;
|
|
9
|
-
from: "api" | "hydrated";
|
|
10
|
-
status: "success";
|
|
11
|
-
profile: {
|
|
12
|
-
id: string;
|
|
13
|
-
stableId: string;
|
|
14
|
-
random: number;
|
|
15
|
-
audiences: string[];
|
|
16
|
-
traits: import("@ninetailed/experience.js-shared").Properties;
|
|
17
|
-
location: {
|
|
18
|
-
coordinates?: {
|
|
19
|
-
latitude: number;
|
|
20
|
-
longitude: number;
|
|
21
|
-
} | undefined;
|
|
22
|
-
city?: string | undefined;
|
|
23
|
-
postalCode?: string | undefined;
|
|
24
|
-
region?: string | undefined;
|
|
25
|
-
regionCode?: string | undefined;
|
|
26
|
-
country?: string | undefined;
|
|
27
|
-
countryCode?: string | undefined;
|
|
28
|
-
continent?: string | undefined;
|
|
29
|
-
timezone?: string | undefined;
|
|
30
|
-
};
|
|
31
|
-
session: {
|
|
32
|
-
id: string;
|
|
33
|
-
isReturningVisitor: boolean;
|
|
34
|
-
landingPage: {
|
|
35
|
-
path: string;
|
|
36
|
-
url: string;
|
|
37
|
-
query: Record<string, string>;
|
|
38
|
-
referrer: string;
|
|
39
|
-
search: string;
|
|
40
|
-
};
|
|
41
|
-
count: number;
|
|
42
|
-
activeSessionLength: number;
|
|
43
|
-
averageSessionLength: number;
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
error: null;
|
|
47
|
-
} | {
|
|
48
|
-
loading: boolean;
|
|
49
|
-
from: "api" | "hydrated";
|
|
50
|
-
status: "error";
|
|
51
|
-
profile: null;
|
|
52
|
-
error: Error;
|
|
53
4
|
};
|
|
5
|
+
/**
|
|
6
|
+
* Custom hook that provides access to the Ninetailed profile state
|
|
7
|
+
* with the 'experiences' property removed to prevent unnecessary re-renders.
|
|
8
|
+
*
|
|
9
|
+
* This hook handles profile state changes efficiently by:
|
|
10
|
+
* 1. Only updating state when actual changes occur
|
|
11
|
+
* 2. Removing the large 'experiences' object from the state
|
|
12
|
+
* 3. Properly cleaning up subscriptions when components unmount
|
|
13
|
+
*
|
|
14
|
+
* @returns The profile state without the 'experiences' property
|
|
15
|
+
*/
|
|
16
|
+
export declare const useProfile: () => UseProfileHookResult;
|
|
17
|
+
export {};
|