-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
[Bug]: forwardRef error: 'className' is missing in props #3684
Comments
Possibly, but it seems like those involve nested forwardRef calls and mine doesn't. The only existing issue I had found was closed as fixed a long time ago but I'm on the latest version. |
in prop-types test code, below code is passed already {
code: `
import React, { forwardRef } from "react";
export interface IProps {
children: React.ReactNode;
type: "submit" | "button"
}
export const FancyButton = forwardRef<HTMLButtonElement, IProps>((props, ref) => (
<button ref={ref} className="MyClassName" type={props.type}>
{props.children}
</button>
));
`,
features: ['ts', 'no-babel'],
} so In prop-types, the forwardRef single use(not with memo) is not a problem I think React.HTMLAttributes type inference error is cause of issue's error, so this issue is same to #3325 |
Except in another project we have HTMLAttributes and we get no errors. I'm not sure what the difference is (it being function vs arrow function didn't change anything). In both cases VSCode/TS properly says the type of export const BaseButton = forwardRef<HTMLButtonElement, PropsWithChildren<ButtonHTMLAttributes<HTMLButtonElement>>>(
function baseButton({ className, pressed, uiVariant, ...props }, ref) {
const classNames = clsx(className, styles.button, uiVariant && styles[uiVariant], {
[styles.pressed]: pressed
})
return <button className={classNames} ref={ref} {...props} />
}
) |
i think the diffrence is PropsWithChildren. To make it more general, the difference arises from importing types from different files. Let me give you an example. If we expand the code you posted by including the import path, it will look like this: import React, { forwardRef, PropsWithChildren } from 'react'
export const BaseButton = forwardRef<HTMLButtonElement, PropsWithChildren<ButtonHTMLAttributes<HTMLButtonElement>>>(
function baseButton({ className, pressed, uiVariant, ...props }, ref) {
const classNames = clsx(className, styles.button, uiVariant && styles[uiVariant], {
[styles.pressed]: pressed
})
return <button className={classNames} ref={ref} {...props} />
}
) and in the code, props-type check is not performed and same thing happens with similar code below // type.ts
interface PropsTypes{
falsyTest:string
}
// test.js
import React from "react"
import {PropsTypes} from "./types"
export const App = (props: PropsTypes) => {
console.log(props.test) // ?? is Ok
return <div></div>;
} We can roughly understand why this phenomenon occurs by looking at the rule code of props-type. The components given as examples above are components.list(); It is returned to the component through , and at this time, if a false value is received from the mustBeValidated function, the subsequent rules are passed. eslint-plugin-react/lib/rules/prop-types.js Lines 189 to 201 in 9f4b2b9
The value to look at in the mustBeValidated function below is ignorePropsValidation, which is defined as true and returns false when the type declaration is imported and loaded as in the example above. eslint-plugin-react/lib/rules/prop-types.js Lines 78 to 86 in 9f4b2b9
For this reason, it appears that no error occurs in the example code. |
I ran into this issue on an updated version, but in a different manner. I was able to find a workaround, but I wanted to post my findings here in case it's of any use: Versions (from
|
|
I usually try to avoid using I've been learning a bit more about how tree-shaking works, but can't say I'm too familiar with it yet. From what I've gathered so far, it seems like using the namespace import pattern isn't a huge issue when used on packages that support ESM along with bundlers like Vite? |
It's always an issue; tree-shaking can never do anywhere near as good as a job as only importing what you need in the first place. Simply having barrel files in your application will make your bundle and memory footprint much larger, no matter what optimizations you attempt to employ. |
I see, thank you! I appreciate the explanation 🙇🏽♂️ Personally, I think I'll choose to not care about it for now since it's just me working on my projects. And I just want to get something out the door and develop as fast as possible. But I'm glad to know this so I can just refactor it all at once in the future 🥴 I think it is slightly unfortunate though that a lot of people using ShadCN might not know this and will continue to use that pattern, since it's what's shown in docs and what will eventually get copy-pasted. |
Indeed, it'd be ideal if they improved their docs to avoid this bad practice. This is all a tangent tho, since we should still work with it :-) |
I think I might have a possible fix. If you think it could be a viable solution, I could submit a PR with this. Disclaimer: I'm not at all familiar with how ESLint rule packages work. This is my first time digging into it. FindingsI found that Possible SolutionAfter I added |
As long as it comes with test cases, that sounds great! |
Cool 🙂 I submitted #3859. |
Is there an existing issue for this?
Description Overview
The following code from shadcn/ui triggers a lint error:
'className' is missing in props validationeslint[react/prop-types)
, except this it definitely defined in the prop types.eslint-config-next 14.1.0
└── eslint-plugin-react 7.33.2
Expected Behavior
eslint-plugin-react version
7.33.2
eslint version
8.56.0
node version
v21.5.0
The text was updated successfully, but these errors were encountered: