I just build a next.js application in that I use react context and react reducer to authenticate users and this is my context code:
import React from "react";
import { createContext, useContext, useReducer } from "react";
import { authConstants } from "./constants";
const Store = createContext();
const reducer = (state, action) => {
switch (action.type) {
case authConstants.LOGIN_REQUEST: {
return {
...state,
user: {
...state.user,
authenticating: true,
},
};
}
case authConstants.LOGIN_SUCCESS: {
return {
...state,
user: {
...action.payload.user,
authenticating: false,
authenticated: true,
},
};
}
case authConstants.LOGIN_FAILURE: {
return {
...state,
user: {
...state.user,
authenticating: false,
authenticated: false,
error: action.payload,
},
};
}
default: {
return state;
}
}
};
export const StoreProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, {
user: {
authenticated: false,
authenticating: true,
error: null,
},
});
return <Store.Provider value={[state, dispatch]}>{children}</Store.Provider>;
};
export const useStore = () => useContext(Store);
and I use a layout component to check the session and redirect unauthenticated users with this code:
import { getSession } from "next-auth/react";
import { useEffect } from "react";
import { useStore } from "../../client/context";
import { authConstants } from "../../client/context/constants";
import { getValue } from "../../utils/common";
import { useRouter } from "next/router";
const Layout = ({ children }) => {
const [state, dispatch] = useStore();
const router = useRouter();
const authFunction = async () => {
const authenticated = getValue(state, ["user", "authenticated"], false);
if (!authenticated) {
dispatch({ type: authConstants.LOGIN_REQUEST });
const session = await getSession();
if (session) {
dispatch({ type: authConstants.LOGIN_SUCCESS, payload: session });
} else {
dispatch({
type: authConstants.LOGIN_FAILURE,
payload: session,
});
router.replace("/auth/login");
}
}
};
useEffect(() => {
authFunction();
}, []);
return children;
};
export default Layout;
and this is my _app.js
import { StoreProvider } from "../client/context";
import { createContext, useContext, useReducer } from "react";
import Layout from "../components/Layout/Layout";
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
return (
<StoreProvider>
<Layout>
<Component {...pageProps} />
</Layout>
</StoreProvider>
);
}
export default MyApp;
For some reason I need to use server-side render in my Login page to get base HTTP authentication from the user :(/pages/auth/login/index.js)
export async function getServerSideProps(ctx) {
const { req, res } = ctx;
const response = await httpAuthCheck(req, res);
return {
props: {},
};
}
and in my middleware, I check base HTTP authentication and redirect the user if there is no base authentication:
import { NextRequest, NextResponse } from "next/server";
export const config = {
matcher: "/auth/:path*",
};
export function middleware(req) {
const basicAuth = req.headers.get("authorization");
const url = req.nextUrl;
if (basicAuth) {
return NextResponse.next();
} else {
return NextResponse.rewrite(url.origin + "/auth/login");
}
}
my problem is hear everything works fine and perfectly without any error in the developer mode of next.js but when I build my application, it is built completely without any error, but when I open my login page with the Server Side Render function I got this error and my server gets down:
TypeError: Cannot read properties of null (reading 'useReducer')
at exports.useReducer (C:\Users\parha\Desktop\nexttest\test\node_modules\react\cjs\react.production.min.js:25:274)
at StoreProvider (C:\Users\parha\Desktop\nexttest\test\.next\server\pages\_app.js:78:61)
at renderWithHooks (C:\Users\parha\AppData\Roaming\npm\node_modules\next\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5471:16)
at renderIndeterminateComponent (C:\Users\parha\AppData\Roaming\npm\node_modules\next\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5544:15)
at renderElement (C:\Users\parha\AppData\Roaming\npm\node_modules\next\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5759:7)
at renderNodeDestructive (C:\Users\parha\AppData\Roaming\npm\node_modules\next\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5898:11)
at renderIndeterminateComponent (C:\Users\parha\AppData\Roaming\npm\node_modules\next\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5598:7)
at renderElement (C:\Users\parha\AppData\Roaming\npm\node_modules\next\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5759:7)
at renderNodeDestructive (C:\Users\parha\AppData\Roaming\npm\node_modules\next\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5898:11)
at renderIndeterminateComponent (C:\Users\parha\AppData\Roaming\npm\node_modules\next\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5598:7)
and this happened just when I run my build application with next start and just happened when I use getServerSideProps function on any page of my application. Please help me!!
I try a lot of things but none of them is working for me!
const [state, dispatch] = useReducer(reducer, { user: { authenticated: false, authenticating: true, error: null, }, });
– Shiflett