Skip to content

Instantly share code, notes, and snippets.

@MuttakinHasib
Last active March 30, 2022 06:44
Show Gist options
  • Save MuttakinHasib/c3ad30fdfcc085cf5e4a447f409f17cc to your computer and use it in GitHub Desktop.
Save MuttakinHasib/c3ad30fdfcc085cf5e4a447f409f17cc to your computer and use it in GitHub Desktop.
Problem with (Redux Toolkit, NRW, Redux Persist) setup
import "../styles/globals.css";
import React, {
ComponentType,
ReactNode,
useMemo,
useState,
useEffect,
} from "react";
import type { AppProps } from "next/app";
import GlobalStyles from "@components/GlobalStyles";
import Layout from "@components/Layouts";
import { Hydrate, QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
import Head from "next/head";
import { wrapper } from "@app/store";
import { MantineProvider } from "@mantine/core";
import { PersistGate } from "redux-persist/integration/react";
import { useStore } from "react-redux";
import { NextComponentType, NextPageContext } from "next";
import { Toaster } from "react-hot-toast";
import baseTheme, { applyTheme } from "themes";
interface Props extends AppProps {
Component: NextComponentType<NextPageContext, any> & {
Layout: ComponentType;
};
}
function MyApp({ Component, pageProps }: Props) {
const [client] = useState<QueryClient>(() => new QueryClient());
const store = useStore();
useEffect(() => {
applyTheme(baseTheme);
}, []);
const PersistWrapper = ({ children }: { children: ReactNode }) => {
return typeof window !== undefined ? (
// @ts-ignore
<PersistGate persistor={store.__persistor} loading={null}>
{children}
</PersistGate>
) : (
<PersistGate persistor={store} loading={null}>
{children}
</PersistGate>
);
};
const page = useMemo(() => {
const PageLayout = Component.Layout || React.Fragment;
return (
<Layout>
<Toaster
// position='top-right'
reverseOrder={false}
// toastOptions={{ style: { marginTop: '4.5rem' } }}
toastOptions={{ duration: 5000 }}
/>
<PageLayout>
<GlobalStyles />
<Head>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>
</Head>
<Component {...pageProps} />
{process.env.NODE_ENV === "development" && <ReactQueryDevtools />}
</PageLayout>
</Layout>
);
}, [Component, pageProps]);
return (
<QueryClientProvider {...{ client }}>
<Hydrate state={pageProps.dehydrateState}>
<PersistWrapper>
<MantineProvider
withGlobalStyles
withNormalizeCSS
theme={{
/** Put your mantine theme override here */
colorScheme: "light",
}}
>
{page}
</MantineProvider>
</PersistWrapper>
</Hydrate>
</QueryClientProvider>
);
}
export default wrapper.withRedux(MyApp);
import { wrapper } from "@app/store";
import CoupleOnboard from "@components/Onboard/Couple";
import { setVenueReference } from "@features/onboard";
import { IVenue } from "@interfaces/venue";
import { getVenue, getVenues } from "@services/venue";
import { GetServerSideProps } from "next";
import React from "react";
interface Props {
venues: IVenue[];
venue: IVenue;
}
const Page = (props: Props) => {
return <CoupleOnboard {...props} />;
};
export default Page;
export const getServerSideProps: GetServerSideProps =
wrapper.getServerSideProps((store) => async ({ query }) => {
try {
const venues = await getVenues();
let venue = null;
if (query.reference) {
venue = await getVenue(query.reference as string);
await store.dispatch(setVenueReference(venue._id));
}
return {
props: {
venues,
venue,
},
};
} catch (err) {
return {
props: {
venues: [],
venue: null,
},
};
}
});
import { onboardCoupleReducer, onboardVenueReducer } from "@features/onboard";
import { userReducer } from "@features/user";
import { combineReducers } from "@reduxjs/toolkit";
export default combineReducers({
"onboard/couple": onboardCoupleReducer,
"onboard/venue": onboardVenueReducer,
user: userReducer,
});
import createWebStorage from "redux-persist/lib/storage/createWebStorage";
const createNoopStorage = () => {
return {
getItem(_key: any) {
return Promise.resolve(null);
},
setItem(_key: any, value: any) {
return Promise.resolve(value);
},
removeItem(_key: any) {
return Promise.resolve();
},
};
};
export const storage =
typeof window !== "undefined"
? createWebStorage("local")
: createNoopStorage();
import {
Action,
AnyAction,
CombinedState,
configureStore,
ThunkAction,
} from "@reduxjs/toolkit";
import { createWrapper, HYDRATE } from "next-redux-wrapper";
import rootReducers from "./reducers";
import { storage } from "./storage";
export const reducers = (
state: ReturnType<typeof rootReducers>,
action: AnyAction
) => {
if (action.type === HYDRATE) {
const nextState = {
...state, // use previous state
...action.payload, // apply delta from hydration
};
if (state.user) {
nextState.user = action.payload.user;
}
console.log(action.payload);
if (state["onboard/couple"]) {
nextState["onboard/couple"] = action.payload["onboard/couple"];
}
if (state["onboard/venue"]) {
nextState["onboard/venue"] = action.payload["onboard/venue"];
}
return nextState;
} else {
return rootReducers(state, action);
}
};
const makeConfiguredStore = (reducer: CombinedState<typeof rootReducers>) =>
configureStore({
reducer,
devTools: true,
middleware: (getDefaultMiddleware) => getDefaultMiddleware(),
});
const makeStore = () => {
const isServer = typeof window === "undefined";
if (isServer) {
return makeConfiguredStore(reducers as CombinedState<typeof rootReducers>);
} else {
// we need it only on client side
const { persistStore, persistReducer } = require("redux-persist");
const persistConfig = {
key: "beweddy",
whitelist: ["onboard/couple", "onboard/venue", "user"], // make sure it does not clash with server keys
storage,
};
const persistedReducer = persistReducer(persistConfig, reducers);
const store = makeConfiguredStore(persistedReducer);
// @ts-ignore
store.__persistor = persistStore(store); // Nasty hack
return store;
}
};
export type AppStore = ReturnType<typeof makeStore>;
export type AppState = ReturnType<AppStore["getState"]>;
export type AppDispatch = AppStore["dispatch"];
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
AppState,
unknown,
Action<string>
>;
export const wrapper = createWrapper<AppStore>(makeStore);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment