Multiple function calls when using custom hook useCallableFunctionResponse
VBota1 opened this issue · comments
Short description
Using the useCallableFunctionResponse
hook from reactfire
causes the function to be called twice.
This might lead to undesired costs.
Version info
React: "^18"
Firebase: "^10.0.0"
ReactFire: "^4.2.3"
Next: "14.1.0"
Node: "^20"
Test case
Content of app/layout.tsx
:
"use client"
import { Inter } from "next/font/google";
import "./globals.css";
import {FirebaseAppProvider} from "reactfire";
const inter = Inter({ subsets: ["latin"] });
const firebaseConfig = {
// your firebase config
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<FirebaseAppProvider firebaseConfig={firebaseConfig}>
<body className={inter.className}>{children}</body>
</FirebaseAppProvider>
</html>
);
}
Content of app/page.tsx
:
"use client"
import {FunctionsProvider, useCallableFunctionResponse, useFirebaseApp} from "reactfire";
import {getFunctions} from "@firebase/functions";
import Test from "@/app/test";
const FUNCTIONS_REGION = 'your region';
export default function Home() {
const firebaseApp = useFirebaseApp();
const functions = getFunctions(firebaseApp, FUNCTIONS_REGION);
return (
<FunctionsProvider sdk={functions}>
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<Test />
</main>
</FunctionsProvider>
);
}
Content of app/test.tsx
:
import {useCallableFunctionResponse} from "reactfire";
export default function Test() {
const responseObservable = useCallableFunctionResponse<any, string>('your_callable_function', {data: {}});
return (
<div>
{
responseObservable.status === 'loading' ?
<p>Loading ...</p> :
<p>{responseObservable.data}</p>
}
</div>
);
}
Steps to reproduce
- Run app (possible with
npm run dev
) - Open app in browser
- In
Firebase console
->Functions
selectyour_callable_function
and open theDetailed usage stats
using the 3 dot menu.
This will open theGoogle Cloud Console
->Function details
page for the function. - Select the
Logs
tab and wait for the logs to load. - Check how many times the function was called when you refreshed the browser page.
Expected behavior
The function should be called once.
202x-xx-xx xx:xx:xx.731 xxx | POST 200 xxx B x ms xxxxxx https://region-project.cloudfunctions.net/your_callable_function
Actual behavior
The function is actually called twice.
202x-xx-xx xx:xx:xx.731 xxx | POST 200 xxx B x ms xxxxxx https://region-project.cloudfunctions.net/your_callable_function
202x-xx-xx xx:xx:xx.798 xxx | POST 200 xxx B x ms xxxxxx https://region-project.cloudfunctions.net/your_callable_function
Workaround
Using the httpsCallable
from firebase/functions
combined with the native hooks useEffect
and useState
solves the issue.
Content of app/test.tsx
:
import {useFunctions} from "reactfire";
import {httpsCallable} from "firebase/functions";
import {useEffect, useState} from "react";
export default function Test() {
const functions = useFunctions();
const dataReader = httpsCallable<object, string>(functions, 'your_callable_function');
const [responseObservable, setResponseObservable] =
useState<{status: string, data: string}>({status: 'loading', data: ''});
useEffect(() => {
dataReader({})
.then((result) => {
setResponseObservable({status: 'success', data: result.data});
})
.catch((error) => {
setResponseObservable({status: 'error', data: error});
});
}, []);
return (
<div>
{
responseObservable.status === 'loading' ?
<p>Loading ...</p> :
<p>{responseObservable.data}</p>
}
</div>
);
}
try google react useeffect called twice