Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hooks + Context not working within Tailwind component #1104

Open
aplr opened this issue Dec 18, 2023 · 6 comments
Open

Hooks + Context not working within Tailwind component #1104

aplr opened this issue Dec 18, 2023 · 6 comments

Comments

@aplr
Copy link

aplr commented Dec 18, 2023

The new Tailwind component makes it quite impossible to use hooks or context w/ react email.

As I'm using react-i18next for i18n, I'm using the useTranslation hook. So I'm not having a dynamic use case either, just using available tools.

Also, I'm using context to pass around some shared data without using prop drilling.

My workaround till now was having Tailwind as my root, so it won't interfere w/ context etc.

However, this won't work with the rewrite, as it's now required to have the <head> as a direct descendant of <Tailwind>.

The hooks issue was also mentioned in #1021, and also what's the probable cause:

@gabrielmfern that does seem a little weird to me, as I do expect hooks to run for other "static" use cases like static site generation or server-side rendering, especially as async server side rendering is becoming more of a thing, and indeed hooks run fine with renderToStaticMarkup. React contexts also work fine in static rendering, the issue is with how the tailwind function traverses the component tree and calls components as plain functions: https://github.com/resendlabs/react-email/blob/2374d0d099360c63fe7427febb239776c3bd6b3b/packages/tailwind/src/tailwind.tsx#L95C32-L95C32.

For now my workaround is using <MyReactContext.Consumer>{context => ...}</MyReactContext.Consumer> instead of the hook.

That's interesting, then I think this is an actual issue with the new Tailwind version, can you open an issue on this so we can reference it on a PR and discuss it there?

Originally posted by @gabrielmfern in #1021 (comment)

@gabrielmfern
Copy link
Collaborator

Certainly something we have in mind and that we intend in fixing ASAP.

@WillsB3
Copy link

WillsB3 commented Nov 18, 2024

@gabrielmfern Do you happen to know if this is now fixed given that #1383 is merged?

@gabrielmfern
Copy link
Collaborator

@WillsB3 Not yet fixed, but this is still going to be an issue that only happens when you have a context inside - as in a child of - the Tailwind component. So, a possible workaround is moving your context provider above Tailwind.

The fix for this is not going to be too hard, I just need to find the time to do it. Will let you know once I do.

@WillsB3
Copy link

WillsB3 commented Nov 20, 2024

Appreciate you sharing the workaround, will give it a go. Thank you 🙏

@makenosound
Copy link

Would still love for this to be fixed, but we’ve worked around it for singleton providers by creating a provider/hook that executes synchronously. Here’s an example for react-intl support:

import { ReactNode } from "react"
import { IntlShape } from "react-intl"

import { Language, getLocaleData } from "."

type IntlContext = { intl: IntlShape; lang: Language }

const ref: {
  intl?: IntlShape
  lang?: Language
} = {
  intl: undefined,
  lang: undefined,
}

export const WithIntl = ({
  children,
  locale,
}: {
  children: ((args: IntlContext) => ReactNode) | ReactNode
  locale?: string
}) => {
  const { intl, lang } = getLocaleData(locale)
  ref.intl = intl
  ref.lang = lang

  if (typeof children === "function") {
    return children({ intl, lang })
  }

  return <>{children}</>
}

export const useIntl = () => {
  if (ref.intl !== undefined && ref.lang !== undefined) {
    return ref as IntlContext
  }
  throw new Error("useIntl called without <WithIntl> provider.")
}

@gabrielmfern
Copy link
Collaborator

Update on this: the issue is a bit harder to fix than I initially thought, there is no simple way to fix it. This is definitely a problem that is going to be here for some time before we can do the big changes for it. The only solutions I can think of require some breaking changes, both in rendering, and in how Tailwind is going to be used with React Email

The issue is that, since we don't and probably won't have a renderer of our own, we have to literally map the entire tree of elements that are children of the Tailwind component to actually inline the styles, but for this to work properly, we also resolve all components that are found, and that breaks the usual lifecycle for React sadly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants