Dominic Henley
Dominic Henley

Reputation: 21

Why doesn't this Context provider in a client component work properly when used in a server component?

I'm working on a project using Next.js App router.

I have two components, one component client and one server component.

// Client component
"use client"

export default function Icon({ name, icon, className = '' } : iconType) {
  
  return (
    <>
      <IconContext.Provider
        value={ { size: "45px" } }
        >
        <div
          className={`flex flex-col ${className}`}
          >
            <div
              className="flex justify-center"
              >
              { icon }
            </div>
            <div
              className="flex justify-center"
              >
              { name }
            </div>
        </div>
      </IconContext.Provider>
    </>
  )
}
// Server component
...
<div
  className="flex justify-center my-10"
  >
   { socials.map((social) => (
     <>
      <Icon
       name={ social.name }
       icon={ social.icon }
      />
     </> ))}
</div>
...

The Context provider in the client component is supposed to resize the Icons that are rendered in the server component. However, it does not do this.

I've tried making the server component a client component by adding the "use client" directive at the top. This makes the Context provider work. However, I do some data fetching in the server component so I don't think this is an ideal solution.

Consulting some other documentation, the way I did it seems to be the intended way of doing it, but I'm having trouble figuring out why it's not really working.

Upvotes: 1

Views: 52

Answers (1)

Ravi Chauhan
Ravi Chauhan

Reputation: 1477

Instead of relying on context, explicitly pass the desired size prop (in this case, "size") from the server component to the Icon component. Update the Icon component to accept the size prop and apply it to the icons:

// Server component
...
<div
  className="flex justify-center my-10"
>
  {socials.map((social) => (
    <>
      <Icon
        name={social.name}
        icon={social.icon}
        size="45px"  // Pass down the size prop
      />
    </>
  ))}
</div>
...


// Client component (Icon)
export default function Icon({ name, icon, size = '', className = '' } : iconType) {
  return (
    <>
      <div
        className={`flex flex-col ${className}`}
        style={{ fontSize: size }}  // Use the passed down size prop
      >
        <div className="flex justify-center">{icon}</div>
        <div className="flex justify-center">{name}</div>
      </div>
    </>
  );
}

If data fetching is essential in the server component, consider using Selective Preboot from @nguniversal/common/modules.

Upvotes: 0

Related Questions