Reputation: 525
I am using Next.js and Redux as a state management. Everything is working perfectly fine except one thing and that is API calls. What I mean by this is that API is being called multiple times even though I dispatched
it just once. When I go and see in the network tab in Google Chrome, I see multiple calls being called.
I am also using Redux Thunk and Redux Toolkit:
import { configureStore } from "@reduxjs/toolkit";
import layoutSlice from "./layoutSlice";
export const store = configureStore({
reducer: {
layout: layoutSlice,
},
});
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
const BASE_URL = "http://localhost:1337";
export const getHeaderData = createAsyncThunk(
"layout/getHeaderData",
async () => {
const response = await axios.get(
`${BASE_URL}/api/navigations?populate=*&sort=id`
);
return response.data;
}
);
export const getFooterData = createAsyncThunk(
"layout/getFooterData",
async () => {
const response = await axios.get(
`${BASE_URL}/api/footers?populate[ContactForm][populate]=*&populate[Links][populate]=*&populate[Info][populate]=*`
);
return response.data;
}
);
const initialState = {
header: [],
footer: [],
isLoadingHeader: false,
isLoadingFooter: false,
};
const layoutSlice = createSlice({
name: "layout",
initialState,
extraReducers: {
[getHeaderData.pending]: (state) => {
state.isLoadingHeader = true;
},
[getHeaderData.fulfilled]: (state, action) => {
state.header = action.payload;
state.isLoadingHeader = false;
},
[getHeaderData.rejected]: (state) => {
state.isLoadingHeader = false;
},
[getFooterData.pending]: (state) => {
state.isLoadingFooter = true;
},
[getFooterData.fulfilled]: (state, action) => {
state.footer = action.payload;
state.isLoadingFooter = false;
},
[getFooterData.rejected]: (state) => {
state.isLoadingFooter = false;
},
},
});
export default layoutSlice.reducer;
import React, { useEffect, useState } from "react";
import { Header, Footer } from "../components";
import { useDispatch, useSelector } from "react-redux";
import { getHeaderData, getFooterData } from "../redux/layoutSlice";
const GeneralLayout = ({ children }) => {
const { isLoadingHeader, isLoadingFooter } = useSelector(
(state) => state.layout
);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getHeaderData());
dispatch(getFooterData());
}, []);
if (isLoadingHeader === true || isLoadingFooter === true) {
return <div>Loading...</div>;
}
return (
<>
<Header />
{children}
<Footer />
</>
);
};
export default GeneralLayout;
I am also using Strapi (dont mind the query for the API call, it works for me so I do not think the problem is there, at least it should not be)
Upvotes: 2
Views: 4822
Reputation: 1
It happens because of react strict mode. React strict mode will render the UI twice so it's sending all request twice. If you want to disable it, you can do it from next.config.js by setting reactStrictMode: false. This will be automatically disable it in production mode.
Upvotes: 0
Reputation: 366
It is because of useEffect
In development, React strictmode calls all effects twice to catch any memory leaks and other issues.
This only applies to development mode, production behavior is unchanged So you don't want to worry about it being called twice in production/build
From official React docs (beta at time of writing)
If your Effect fetches something, the cleanup function should either abort the fetch or ignore its result:
useEffect(() => {
let ignore = false;
async function startFetching() {
const json = await fetchTodos(userId);
if (!ignore) {
setTodos(json);
}
}
startFetching();
return () => {
ignore = true;
};
}, [userId]);
Read more here
Upvotes: 4
Reputation: 1
You must add a dispatch to dependency of useEffect function.. make sure the peomise function receives parameter as the informations you want to get or post.. And call the parameter inside axios func after APIurl.
Upvotes: 0