Skip to content

Commit

Permalink
fix(hooks): fix stale api state on connection retry (#1606)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitayutanov authored Jul 31, 2024
1 parent bdeb631 commit aa9b9e4
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 16 deletions.
2 changes: 1 addition & 1 deletion utils/gear-hooks/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@gear-js/react-hooks",
"version": "0.11.0",
"version": "0.11.1",
"description": "React hooks used across Gear applications",
"author": "Gear Technologies",
"license": "GPL-3.0",
Expand Down
20 changes: 5 additions & 15 deletions utils/gear-hooks/src/context/Api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ const { Provider } = ApiContext;
function ApiProvider({ initialArgs, children }: Props) {
const [api, setApi] = useState<GearApi>();
const providerRef = useRef<WsProvider | ScProvider>();
const providerUnsubRef = useRef<() => void>();

const switchNetwork = async (args: ProviderArgs) => {
// disconnect from provider instead of api,
// cuz on failed GearApi.create connection is already established,
// but api state is empty
if (providerRef.current) {
if (providerRef.current && providerUnsubRef.current) {
setApi(undefined);
await providerRef.current.disconnect();
providerUnsubRef.current();
}

const isLightClient = 'spec' in args;
Expand All @@ -68,21 +70,9 @@ function ApiProvider({ initialArgs, children }: Props) {
: new WsProvider(args.endpoint, args.autoConnectMs, args.headers, args.timeout);

providerRef.current = provider;
providerUnsubRef.current = provider.on('connected', async () => setApi(await GearApi.create({ provider })));

// on set autoConnectMs connection starts automatically,
// and in case of error it continues to execute via recursive setTimeout.
// cuz of this it's necessary to await empty promise,
// otherwise GearApi.create would be called before established connection.

// mostly it's a workaround around React.StrictMode hooks behavior to support autoConnect,
// and since it's based on ref and WsProvider's implementation,
// it should be treated carefully
await (isLightClient || (args.autoConnectMs !== undefined && !args.autoConnectMs)
? provider.connect()
: Promise.resolve());

const result = await GearApi.create({ provider });
setApi(result);
if (isLightClient) await provider.connect();
};

useEffect(() => {
Expand Down

0 comments on commit aa9b9e4

Please sign in to comment.