Inconsistent store state for SSG pages #532
-
I have a project which generates about 1200 static pages, using Here are the debug logs showing this happening in my project, note how the LOGS
`store.js`import { configureStore } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/dist/query';
import { createWrapper } from 'next-redux-wrapper';
import { bookingApi } from '../services/bookingApi';
import { s3Api } from '../services/s3Api';
export function makeStore() {
return configureStore({
reducer: {
[s3Api.reducerPath]: s3Api.reducer,
[bookingApi.reducerPath]: bookingApi.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(s3Api.middleware).concat(bookingApi.middleware),
devTools: true,
});
}
const store = makeStore();
setupListeners(store.dispatch);
export const wrapper = createWrapper(() => store, { debug: true }); `s3Api.ts`import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { HYDRATE } from 'next-redux-wrapper';
const BASE_URL = 'https://...';
const VENUE_VERSION = '4';
// Define a service using a base URL and expected endpoints
/**
* Utilizes @reduxjs/toolkit createApi to create an api service.
* @see https://redux-toolkit.js.org/rtk-query/api/createApi
*/
export const s3Api = createApi({
reducerPath: 's3Api',
baseQuery: fetchBaseQuery({ baseUrl: BASE_URL }),
extractRehydrationInfo(action, { reducerPath }) {
if (action.type === HYDRATE) {
return action.payload[reducerPath];
}
},
tagTypes: [],
endpoints: (builder) => ({
getVenuesList: builder.query<Venue[], { lang: string; slim: boolean }>({
query: ({ lang, slim }) => `venues/${lang}/all${slim ? '.slim' : ''}.${VENUE_VERSION}.json`,
}),
getVenueById: builder.query<Venue, { lang: string; venueId: string | string[]; slim: boolean }>(
{
query: ({ lang, venueId, slim }) =>
`venue/${lang}/${venueId}${slim ? '.slim' : ''}.${VENUE_VERSION}.json`,
},
),
}),
});
// Export hooks for usage in function components, which are
// auto-generated based on the defined endpoints
export const {
useGetVenueByIdQuery,
useGetVenuesListQuery,
util: { getRunningQueriesThunk },
} = s3Api;
export const { getVenueById, getVenuesList } = s3Api.endpoints;
`example-usage.tsx`type Props = PropsWithStrings<{ preview: boolean; locale?: string }>;
export default function VenuePage({ strings, preview, locale = '' }: Props) {
const {
query: { venueId },
isFallback,
} = useRouter();
const result = useGetVenueByIdQuery(
{ lang: locale, venueId: venueId as string, slim: true },
{ skip: isFallback },
);
return (
<Container>
{/* omitted */}
</Container>
);
}
export const getStaticPaths = async function (context): Promise<GetStaticPathsResult> {
// Create a temporary store just to dispatch
const store = makeStore();
// Dispatch action and get results to create paths
const result = await store.dispatch(getVenuesList.initiate({ lang: 'en', slim: true }));
const paths = result.data.flatMap((venue) =>
locales.map((locale) => ({ params: { venueId: venue.id }, locale })),
);
const gspResult: GetStaticPathsResult = gsp ? await gsp(context) : null;
return {
paths: [...paths, ...(gspResult?.paths || [])],
fallback: typeof gspResult?.fallback === 'boolean' ? gspResult.fallback : true,
};
};
export const getStaticProps: GetStaticPropsWithStrings = wrapper.getStaticProps(
(store) =>
async ({ locale, params }) => {
const venueId = params?.venueId as string;
if (typeof venueId === 'string') {
// Prepare the store for the coming getVenueById call (called via hook in component)
store.dispatch(getVenueById.initiate({ lang: locale || '', venueId, slim: true }));
}
// Wait for the dispatch to finish before generating page
await Promise.all(store.dispatch(getRunningQueriesThunk()));
return {
props: { locale },
// If webhooks isn't setup then attempt to re-generate in 1 minute intervals
revalidate: process.env.SANITY_REVALIDATE_SECRET ? undefined : 60,
};
},
); I've now tried to replicate this in the example here but for some reason that doesn't happen in that project. LOGS
ScreenshotsEarly in the build logsLater in the build logsDesktop
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
I believe I finally found it. With a few strands of hair left on my scalp. Apparently the store wasn't being created properly by the wrapper when passed in like the before part of below diff. If anyone has pointers as to how to attach the listeners via |
Beta Was this translation helpful? Give feedback.
I believe I finally found it. With a few strands of hair left on my scalp.
Apparently the store wasn't being created properly by the wrapper when passed in like the before part of below diff. If anyone has pointers as to how to attach the listeners via
setupListeners
I'd love to know, but right now I think I can do without them.