Cannot read properties of null (reading 'useReducer') when I build my next.js application in Server Side Render page
Asked Answered
B

1

7

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!

Barrens answered 10/12, 2022 at 15:6 Comment(6)
Try adding break;'s to the switch caseShiflett
It looks like nothing is returned from the useReducer call on the lines: const [state, dispatch] = useReducer(reducer, { user: { authenticated: false, authenticating: true, error: null, }, });Shiflett
This code works correctly in the developer mode of next.js without any error but in the built version of that I got that errorBarrens
Hmm, I'll dive deeper now thenShiflett
Did you find any fix?Robinson
@Barrens Did you fix the error?Decahedron
W
0

It seems you are using the hooks outside a component. Hooks must be used within components. Try to fix this and see the result

Whitehall answered 12/3 at 7:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.