Date of slack thread: 7/5/24
Anonymous: For some reason, using client.updateUserAsync removes the provider’s children (unmounts the component) and adds them back (mount component), causing our app to flicker when the user information gets loaded and set on the client. Did anyone else experience this? Is there a workaround?
Anonymous: Apparently there’s no such prop on the new provider component Property 'mountKey' does not exist on type 'IntrinsicAttributes & StatsigProviderProps'
Anonymous: Hey Gabriel - Can you share the code snippet of where you initialize Statsig & updateUser?
Anonymous: Also, if you can include what version you’re using, that would be great!
Anonymous: Hi! I’m using version 1.4.0
Anonymous: here’s my component :
import nullThrows from '@shared/utils/nullThrows';
import { StatsigClient } from '@Statsig/js-client';
import { StatsigProvider } from '@Statsig/react-bindings';
import { runStatsigSessionReplay } from '@Statsig/session-replay';
import { runStatsigAutoCapture } from '@Statsig/web-analytics';
import getFavoriteTeamId from 'features/team/selectors/getFavoriteTeamId';
import getTeamId from 'features/team/selectors/getTeamId';
import { getUser } from 'features/user/user.selectors';
import { useEffect, useMemo, useState } from 'react';
import { useAppSelector } from 'store';
import Preloader from 'shared/components/Preloader';
function useAsyncClient(): { isLoading: boolean; client: StatsigClient } {
const [isLoading, setIsLoading] = useState(true);
const client = useMemo(() => {
const statsigClient = new StatsigClient(
nullThrows(process.env.REACT_APP_STATSIG_CLIENT_TOKEN),
{},
{
environment: { tier: process.env.REACT_APP_STATSIG_ENVIRONMENT },
},
);
runStatsigSessionReplay(statsigClient);
runStatsigAutoCapture(statsigClient);
statsigClient
.initializeAsync()
.then(() => {
setIsLoading(false);
})
.catch((err) => {
console.error(err);
});
return statsigClient;
}, []);
return { client, isLoading };
}
function StatSigProvider({ children }: { children: React.ReactNode }) {
const favouriteTeamId = useAppSelector(getFavoriteTeamId);
const teamId = useAppSelector(getTeamId) || favouriteTeamId;
const user = useAppSelector(getUser);
const { client, isLoading } = useAsyncClient();
useEffect(() => {
if (client && user?.id && teamId) {
client.updateUserAsync({
userID: user?.id.toString(),
customIDs: { teamID: teamId.toString() },
});
}
}, [teamId, user?.id, client]);
if (isLoading) {
return <Preloader />;
}
return <StatsigProvider client={client}>{children}</StatsigProvider>;
}
export default StatSigProvider;
Sophie (Statsig): Thanks for including the information! Where were you trying to call for the mountKey
& getting the error that you saw above?
Anonymous: return <StatsigProvider client={client}>{children}</StatsigProvider>;
Anonymous: I tried adding mountKey
as a prop on the <StatsigProvider
component
Tore (Statsig): The mountKey
prop is on the old react sdk, not the react bindings you are using here, sorry for the confusion from the bot.
Anonymous: yes, I noticed. Is there an equivalent in the new react sdk?
Tore (Statsig): Not yet. I think we probably need an sdk update here
Anonymous: Could you suggest a workaround that I could use until that update is out? The flickering introduced by updateUserAsync
is pretty annoying
Tore (Statsig): The fastest way would be to write your own provider. In this case, the provider renders the children only when the status is ready
Anonymous: The thing is that one of the children triggers the request that gets the userId and teamId that I need to set on the statsig user, so I need to render the children. My expectation was that the statsig provider would not unmount and remount the children when the user gets updated, but it just triggers a re-render
Tore (Statsig): I understand that completely. For now, the easiest thing to do would be to just copy that provider but always render the children
Anonymous: I’ll give that a try