Next.js Discord

Discord Forum

nextjs app router utils.js

Unanswered
Varun posted this in #help-forum
Open in Discord
I am making a utils.js and I put it in my src/app directory. if i try importing next/headers

Error:
× You're importing a component that needs next/headers. That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component.

what could this utils files parents be that next is complaining about?

23 Replies

Giant Angora
If you import next/headers you can only import utils.js into Server Components, you are probably importing utils.js in a Client Component.

Just create a separate file for server-side utilities that use stuff like next/headers
@Giant Angora If you import `next/headers` you can only import `utils.js` into Server Components, you are probably importing `utils.js` in a Client Component. Just create a separate file for server-side utilities that use stuff like `next/headers`
// In your page component file

import CreateNewDraft from './draftIdEditClient';
import { getTokens } from 'next-firebase-auth-edge/lib/next/tokens';
import { cookies } from 'next/headers';
import { authConfig } from '../../../../config/server-config';
import { toUser } from '../../../../components/user';
import withSubscription from '../../../../subWrapper';

function DraftEditPage({ uid, params }) {
  // Now, this component directly receives all the necessary props.
  return <CreateNewDraft uid={uid} params={params} />;
}

export const getServerSideProps = async ({ params }) => {
  const tokens = await getTokens(cookies(), authConfig); 
  const userInfo = toUser(tokens);

  return {
    props: {
      uid: userInfo.email,
      params, 
    },
  };
};

// Here you apply the subscription HOC
export default withSubscription(DraftEditPage, ['premium', 'enterprise']);


I am tryna do getServerSideProps but im using app router so its not letting me. i tried reading the docs but am a bit confused on how I can do this

any ideas?
Giant Angora
Prolly better to submit another question as its not related
// hoc/withSubscription.js
import React from 'react';
import { useRouter } from 'next/navigation';
import { getSubscriptionByEmail } from './components/utils';
import { getUserEmailFromCookies } from './server_utils';

const withSubscription = async (WrappedComponent, allowedPlans) => {
  return async (props) => {

    const uid = await getUserEmailFromCookies();
    const currentUserPlan = await getSubscriptionByEmail(uid);
    const router = useRouter();

    if (!allowedPlans.includes(currentUserPlan)) {

      useEffect(() => {
        router.push('/webapp/pricing');
      }, []);

      return null; // Or a loading indicator
    }

    return <WrappedComponent {...props} />;
  };
};

export default withSubscription;
@Varun its server_utils here
yeah you can't use headers() function in client component
what are some ways I can work around that then?
yea i use firebase auth
but subscriptions managed by stripe
have you checked their example repo?
yea all my auth stuff works fine with the cookies and stuff but I ran into problems when trying to incorporate stripe subscriptions into my app. I get their subscription by calling a getSubscription function with their email
maybe I should include subscription in my context that includes the email
like create a route handler or server action for the subscription
'use server'

import { getTokens } from 'next-firebase-auth-edge/lib/next/tokens';
import { cookies } from 'next/headers';

export async function getSubscriptionByEmail() {
   const tokens = await getTokens(cookies(), authConfig); 
   const userInfo = toUser(tokens);

   const currentUserPlan = await getSubscriptionByEmail(userInfo.uid);

   return { currentUserPlant }
}
ok cool ill look into route handlers
thanks
yea I just aded it to my user object and it worked instead of treating as 2 seperate entities and added checks in my middleware,.js instead of the component wrapper
thanks!