preview server (`email dev`) does not work with any React hook
Describe the Bug
I tried using React context in my email templates, which works perfectly fine with the render package, but breaks with the email dev command.
I get the following error on the console:
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
Complete console output
$ email dev
✔ Emails preview generated
⠋ Installing dependencies...
[1/4] Resolving packages...
warning workspace-aggregator-f031c1ce-e58a-457c-a803-e5cf375879b8 > react-email-client > @types/[email protected]: This is a stub types definition. classnames provides its own type definitions, so you do not need this installed.
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
✔ Dependencies installed
warning From Yarn 1.0 onwards, scripts don't require "--" for options to be forwarded. In a future version, any explicit "--" will be forwarded as-is to the scripts.
$ next dev -p 3000
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
warn - You have enabled experimental feature (appDir) in next.config.js.
warn - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk.
info - Thank you for testing `appDir` please leave your feedback at https://nextjs.link/app-feedback
event - compiled client and server successfully in 935 ms (262 modules)
wait - compiling...
event - compiled client and server successfully in 147 ms (262 modules)
wait - compiling /_error (client and server)...
event - compiled client and server successfully in 48 ms (263 modules)
warn - Fast Refresh had to perform a full reload due to a runtime error.
wait - compiling /preview/[slug]/page (client and server)...
event - compiled client and server successfully in 2.7s (1433 modules)
wait - compiling...
event - compiled successfully in 172 ms (746 modules)
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
error - TypeError: Cannot read properties of null (reading 'useContext')
at useCtx (./emails/components/context.tsx:12:64)
at Foo (./emails/components/foo.tsx:14:70)
error - TypeError: Cannot read properties of null (reading 'useContext')
at useCtx (./emails/components/context.tsx:12:64)
at Foo (./emails/components/foo.tsx:14:70)
digest: "2702191682"
error - TypeError: Cannot read properties of null (reading 'useContext')
at useContext (/Users/bergold/Sources/_tmp/react-email-reproductions/react-email-starter/node_modules/next/dist/compiled/react/cjs/react.development.js:1753:21)
at useCtx (webpack-internal:///./emails/components/context.tsx:12:64)
at Foo (webpack-internal:///./emails/components/foo.tsx:14:70)
at renderWithHooks (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7042:26)
at renderIndeterminateComponent (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7101:25)
at renderElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7292:21)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7431:29)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderNode (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7555:24)
at renderChildrenArray (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7517:21)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7462:21)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderNode (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7555:24)
at renderHostElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7029:13)
at renderElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7297:17)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7431:29)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderNode (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7555:24)
at renderHostElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7029:13)
at renderElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7297:17)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7431:29)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderNode (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7555:24)
at renderHostElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7029:13)
at renderElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7297:17)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7431:29)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderNode (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7555:24)
at renderHostElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7029:13)
at renderElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7297:17)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7431:29)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderForwardRef (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7209:17)
at renderElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7348:29)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7431:29)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderNode (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7555:24)
at renderHostElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7029:13)
at renderElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7297:17)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7431:29)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderIndeterminateComponent (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7143:21)
at renderElement (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7292:21)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7431:29)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderNode (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7555:24)
at renderChildrenArray (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7517:21)
at renderNodeDestructiveImpl (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7462:21)
at renderNodeDestructive (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7407:28)
at renderNode (webpack-internal:///(sc_server)/../node_modules/next/dist/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js:7555:24) {
page: '/preview/notion-magic-link'
}
Which package is affected (leave empty if unsure)
react-email
Link to the code that reproduces this issue
https://github.com/bergold/react-email-usecontext
To Reproduce
- Checkout the linked reproduction repository
- Make note of the use of...
-
createContextinemails/components/context.tsx -
Providerinemails/notion-magic-link.tsx -
useContextinemails/components/foo.tsx
-
- Install deps
yarn - Run
yarn run dev - Open localhost:3000/preview/notion-magic-link in your browser
- Observe the error in your terminal output
Expected Behavior
No errors and the <Foo /> component should render the context value.
What's your node version? (if relevant)
18.14.0
@bukinoshita any suggestions for getting to the bottom of this issue? I dug around a bit and guess that this problem probably relates to having multiple versions of React, since the client ends up using a version of react dom that's bundled with nextjs (based on the stacktrace, something like version 18.3.0-next-3706edb81-20230308 for me locally). I've been able to confirm that it is only an issue with the client invoking render and is not an issue when invoking render directly.
@bukinoshita I think this is actually a nextjs issue: https://github.com/vercel/next.js/issues/49355
I've found that if I manually update my local .react-email/package.json to use "next":"13.4.4", my useContext problems go away. A colleague of mine was able to have success by doing the same.
I can confirm that I have the same issue when using react-email and locally updating next to 13.4.4 solved it for me too.
I have the same problem with react-email 2.0.0. It seems all hooks(client side) are broken. It would normally not necessary to have state in emails but some libraries like the ones used for translations need it (useContext and typesafe-i18n seems to be using useState()).
And btw, the render function works fine even with client side hooks.
Any updates on this?
@tecoad AFAIK this is working, just the support for it with Tailwind that is flaky.
I have the same problem with react-email 2.0.0
@bn3t Is this also the case with 2.1.0?
@gabrielmfern I just tested it with 2.1.0 and it's broken.
Trying to use the following component
function TestComponent() {
const containerRef = useRef(0);
return <div ref={containerRef} />;
};
throws :point_down: during email export/preview
TypeError: Cannot read properties of null (reading 'useRef')
@mewa So this component is the email template, or does is it a component imported into an email template?
It's imported into an email template.
I'm also getting 3rd party issues.
I thought I could side step it with renderToString, but then none of those elements get any of the tailwind css transformations needed to display those styles 🤔
Got this error happening on our latest canary as well, I'll start taking a look at this right now.
Got a fix working for this, will close this one once we release #1431 as a stable release, and will let you know once it's on canary.
This has been fixed and released under a canary version, see [email protected] and upgrade to [email protected] to get it working.
Using the latest cannary version ("@react-email/components": "0.0.18-canary.0" and "react-email": "2.1.3-canary.1") the export is failing.
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. /Users/julio/react-email/react-email-starter/out/transfer_details_policy.js:1395 return dispatcher.useContext(Context); ^ TypeError: Cannot read properties of null (reading 'useContext') at useContext4 (/Users/julio/react-email/react-email-starter/out/transfer_details_policy.js:1395:29) at useTranslation (/Users/julio/react-email/react-email-starter/out/transfer_details_policy.js:116885:36) at useTranslation2 (/Users/julio/react-email/react-email-starter/out/transfer_details_policy.js:117039:15) at Object.TransferDetailsPolicy (/Users/julio/react-email/react-email-starter/out/transfer_details_policy.js:117062:22) at exportTemplates (/Users/julio/react-email/react-email-starter/export.ts:92:26)
@JulioFerrero Nice! Thanks for letting me know, should be an easy fix and I'll release a canary for that soon as well.
@JulioFerrero This should be fixed on a new canary I just released [email protected]
Thanks @gabrielmfern I am able to use React Context now, although FYI I need the provider to exist outside of the Tailwind component.
@JulioFerrero This should be fixed on a new canary I just released
[email protected]
Thaaaaaaanks! I just saw it and it works!!!
I setup a new project using npx [email protected](it uses "@react-email/components": "0.0.18-canary.0" and "react-email": "2.1.3-canary.2").
I run npm run export in this new project without adding any new code and just the default templates that come with it.
The command fails with output:
❌ Failed to build emails undefined undefined
I am using Node v18.16.1.
@Dhruv88 Not sure what that is, can you make a new issue for that? Seems like that is something else unrelated to this one.
This has been fixed and release under [email protected]. If anyone still experiences issues with this, let me know and I'll reopen.