Reputation: 73
I made a simple Async function and wanted to test run it in my react app. The function is:
async function WAIT(time: any) {
await new Promise((r) => setTimeout(r, time))
}
export async function GetMemberList(orgId: string):Promise<ResponseInterface>{
await WAIT(3000);
return {code: 404, data: "Data"}
}
And i try to call it in my main app like this:
function App() {
async function fn() {
let x = await GetMemberList('SOme');
console.log(x);
}
fn();
return (<div>.....<div>)
}
But the problem is console.log(x)
runs twice. I get {code: 404, data: "Data"} twice. Why is that? Thanks
Upvotes: 0
Views: 5360
Reputation: 641
By calling fn() directly in your component, it will trigger every time your component renders. This can happen for many reasons.
You can avoid this with useEffect, and specify the dependencies of the function. In this case, it's only the function itself.
function App() {
async function fn() {
let x = await GetMemberList('SOme');
console.log(x);
}
useEffect(() => {
fn();
}, [fn]);
return (<div>.....<div>)
However, since fn is redefined every time the component renders, it would still be called every time.
In this specific case, you should define the function outside of the component. It doesn't depend on any data provided by the component, so it's basically a static function. It will never change. In this case, you can safely remove fn from the dependency array
async function fn() {
let x = await GetMemberList('SOme');
console.log(x);
}
function App() {
useEffect(() => {
fn();
}, []);
return (<div>.....<div>)
There are other ways to do this too. You can define the fn function inside the useEffect, and you can define it with useCallback, so that it will have a stable reference between renders.
function App() {
useEffect(() => {
async function fn() {
let x = await GetMemberList('SOme');
console.log(x);
}
fn();
}, []);
return (<div>.....<div>)
With useCallback:
function App() {
const cb = useCallback(async() => {
let x = await GetMemberList('SOme');
console.log(x);
}, []);
useEffect(() => {
cb();
}, [cb]);
return (<div>.....<div>)
Upvotes: 0
Reputation: 10658
Here's the solution:
function App() {
async function fn() {
let x = await GetMemberList('SOme');
console.log(x);
}
React.useEffect(() => {
fn();
}, []);
return (<div>.....<div>)
}
Making use of useEffect
with an empty dependency array will make it so that the fn()
only gets called once upon the App
component mounting.
Upvotes: 2
Reputation: 4005
I tried running your code and it's outputting once.
Most probably, the problem is that something is triggering a rerender in your template and the fn()
is getting called again.
You can easily verify it by wrapping your fn()
inside of a useEffect()
.
Upvotes: 1