Open dbalatero opened 9 months ago
Thanks for reporting @dbalatero. Are you able to share the full snippet of how to reproduce the issue as well as the version you are seeing this on?
I attempted to repro using v1.34.0 but am seeing it default to isLoading:true.
Here is my snippet:
import { StatsigProvider, useGate } from "statsig-react";
import "./App.css";
var states: unknown[] = [];
function GateOne() {
const gate = useGate("a_gate");
states.push(gate.isLoading);
return (
<div>
a_gate: {gate.value ? "Pass" : "Fail"} {JSON.stringify(states)}
</div>
);
}
function App() {
states.push("Start");
return (
<StatsigProvider
sdkKey="client-111111"
user={{ userID: "a-user" }}
>
<GateOne />
</StatsigProvider>
);
}
export default App;
This results in a page with:
a_gate: Pass ["Start",true,true,false]
I can try to repro it again and figure out how.
Before I do that, one existential question I have pertains to the TypeScript shape I found for useGate
's return type:
The comment says Returns the initialization state of the SDK and a gate value
– does isLoading
mean:
false
?
ORtrue
-> false
?I initially interpreted isLoading
as option 2, but I think it might be option 1?
Oh and to answer your version question, I'm on 1.27.3.
We make a single network request to fetch all the gate/experiment values for the given user. isLoading
is representing that network request, and will resolve to false
once the network response is processed.
It is set here: https://github.com/statsig-io/react-sdk/blob/main/src/StatsigHooks.ts#L19-L45
Which comes from the StatsigContext: https://github.com/statsig-io/react-sdk/blob/main/src/StatsigProvider.tsx#L185 https://github.com/statsig-io/react-sdk/blob/main/src/StatsigProvider.tsx#L221
I am guessing anyone using StatsigSynchronousProvider
in React Strict mode will run into the same issue.
This happens because of this useEffect
here:
useEffect(() => {
if (firstUpdate.current) {
// this is the first time the effect ran
// we dont want to modify state and trigger a rerender
// and the SDK is already initialized/usable
firstUpdate.current = false;
if (typeof window !== 'undefined') {
window.__STATSIG_SDK__ = Statsig;
window.__STATSIG_JS_SDK__ = StatsigJS;
window.__STATSIG_RERENDER_OVERRIDE__ = () => {
setUserVersion(userVersion + 1);
};
}
return;
}
// subsequent runs should update the user
setInitialized(false);
Statsig.updateUser(user).then(() => {
setUserVersion(userVersion + 1);
setInitialized(true);
});
}, [userMemo]);
Because of Strict mode, the component is rendered twice, and the effect will run on mount, setting initialized
to false
and calling updateUser
- which I am guessing is what is hitting /initialize
.
shutdownOnUnmount
is also broken on Strict mode.
For now, the best option I've found is setting localMode
to true
.
I'm seeing an issue with the
useGate
hook whereisLoading
starts in thefalse
state.To reproduce, add this to a React component:
I see the following print statements:
Problems
isLoading
starts asfalse
, there's no way to block a render until a gate value comes back for real.value
flips totrue
whileisLoading
is alsotrue
. This is a little odd to see the value change, but it might be because you're doing 2setState
calls in a row.