Styling a component with forwardRef
Environment
- Linaria version: @linaria/core 6.2.0, @linaria/react 6.2.1
- Next.js 14.2.5, next-with-linaria 0.7.0
- Node.js version: 20.16.0
- OS: macOS 14.5
Description
Hi, I'm using Linaria in a Next project via next-with-linaria.
In a file marked with 'use client', I have a component defined with forwardRef that accepts styles:
const StylableInputFwdRef = forwardRef<HTMLInputElement, StylableInputProps>(({ label, className, style }, ref) =>
<p>
<label>
{label}{" "}
<input ref={ref} className={ className } style={ style } />
</label>
</p>
);
I would like to style this component with Linaria:
const InputLinariaFwdRef = styled(StylableInputFwdRef)`
border: 2px inset blue;
`;
This declaration raises an error:
next14-linaria/node_modules/@wyw-in-js/transform/lib/module.js:224
throw new EvalError(`${e.message} in${this.callstack.join('\n| ')}\n`);
^
EvalError: TextEncoder is not defined in next14-linaria/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js
| next14-linaria/node_modules/next/dist/server/future/route-modules/app-page/module.compiled.js
| next14-linaria/node_modules/next/dist/server/future/route-modules/app-page/vendored/rsc/react.js
| next14-linaria/src/app/ClientComponent.tsx
at evalFile.next (<anonymous>)
The error seems to happen in Next.js code but is re-thrown by wyw-in-js.
I'm not sure whether my problem is caused by Linaria itself, by next-with-linaria, wyw-in-js or Next.js. I'd appreciate any hints.
Is is possible to wrap a component with forwardRef? Am I fundamentally misunderstanding how Linaria works in a client component?
Thanks for your time and thank you for this project!
Reproducible Demo
Fresh Next.js project with Linaria: https://github.com/molily/next14-linaria Relevant code is in https://github.com/molily/next14-linaria/blob/main/src/app/ClientComponent.tsx
- npm install
- npm run dev
- Go to http://localhost:3000
Hi,
the issue seems to be a typing issue of forwardRef. Assigning the return-type of forwardRef to StylableInputFwdRef works:
- const StylableInputFwdRef = forwardRef<HTMLInputElement, StylableInputProps>(({ label, className, style }, ref) =>
+ const StylableInputFwdRef: React.ForwardRefExoticComponent<React.PropsWithoutRef<StylableInputProps> & React.RefAttributes<HTMLInputElement>> = forwardRef(({ label, className, style }, ref) =>
Note that linaria's styled already calls forwardRef on every component regardless whether it's necessary or not.
Any updates on this? I tried the suggested solution, but it didn’t work.
Hi,
the issue seems to be a typing issue of
forwardRef. Assigning the return-type offorwardReftoStylableInputFwdRefworks:
- const StylableInputFwdRef = forwardRef<HTMLInputElement, StylableInputProps>(({ label, className, style }, ref) =>
- const StylableInputFwdRef: React.ForwardRefExoticComponent<React.PropsWithoutRef<StylableInputProps> & React.RefAttributes<HTMLInputElement>> = forwardRef(({ label, className, style }, ref) => Note that linaria's
styledalready callsforwardRefon every component regardless whether it's necessary or not.
Thanks for the answer. I had the same issue, and your solution worked for me. Could you please explain why assigning the return type is actually needed? Is there any other workaround?
@EdiAfremovFactify linaria's styled never returns a ForwardRefExoticComponent no matter the type of the component passed as its first argument. It is just missing a type signature handling that special case.
If this solved your issue, too, @molily it'd be great if you could close the issue.