Next.js Discord

Discord Forum

Passing server side props into deeply nested components

Answered
African Slender-snouted Crocodil… posted this in #help-forum
Open in Discord
Avatar
African Slender-snouted CrocodileOP
getServerSideProps can [only be exported from a page](https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props#behavior). This makes sense. However, I am wondering if there is an idiomatic way to pass these props into deeply nested components without using prop-drilling. useContext isn't appropriate since it's a react hook that can only be run on the client.

Something like:
// pages/profile.tsx
export const getServerSideProps = async () => {
    // fetch user data from database
    const res = await fetch("...");
    const data = await res.json();
    return {
        props: {
            isSubscribed: data.isSubscribed
        }
    }
}

export const ProfilePage = (props) -=> {
    return (
      <PageLayout isSubscribed={props.isSubscribed}>
      { ... }
      </PageLayout>  
    )
}

Then what if I want to pass isSubscribed to a <Nav /> component and then pass that to the <LoginButton /> component, which then passes it down to something else...

How do I avoid prop drilling in this case?
Answered by African Slender-snouted Crocodile
For future me or anyone
getServerSideProps:
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
  const subscriptionStatus = await getSubscriptionStatus(ctx)
  return {
    props: {
      isSubscribed: subscriptionStatus.isSubscribed,
    },
  }
}

Then the page
export default function Home(
  props: InferGetServerSidePropsType<typeof getServerSideProps>
) {
  const { isSubscribed } = props
  return (
    <SubscriptionProvider isSubscribed={isSubscribed}>
      <Layout></Layout>
    </SubscriptionContext>
   )
}

Then in deeply nested components...
const {isSubscripted} = useSubscription()
View full answer

4 Replies

Avatar
joulev
you are using the pages router (getServerSideProps only works in the pages router). then just use useContext or any client-side state management libraries of your choice. all components in the pages router are client components.
Avatar
African Slender-snouted CrocodileOP
yeah I ended up going with a <SubscriptionContext /> and just wrapping each (necessary) page with that. then initializing the context at the top level page component using the data from getServerSideProps
Avatar
African Slender-snouted CrocodileOP
For future me or anyone
getServerSideProps:
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
  const subscriptionStatus = await getSubscriptionStatus(ctx)
  return {
    props: {
      isSubscribed: subscriptionStatus.isSubscribed,
    },
  }
}

Then the page
export default function Home(
  props: InferGetServerSidePropsType<typeof getServerSideProps>
) {
  const { isSubscribed } = props
  return (
    <SubscriptionProvider isSubscribed={isSubscribed}>
      <Layout></Layout>
    </SubscriptionContext>
   )
}

Then in deeply nested components...
const {isSubscripted} = useSubscription()
Answer
Avatar
African Slender-snouted CrocodileOP
Thx