eslint-plugin-react: button-has-type does not allow for dynamic assignment
My Button component allows to override the type arg but button-has-type is still complaining about. It seems it does not validate the real AST path of prop assignment
Button = ({ type = "button" }) => <button type={type}/>
Button.propTypes = {
type: PropTypes.arrayOf(["submit", "button", "reset"]),
Does the plugin have access to the propTypes and can match that the only possible allowed values are within the rules allowed values and that the default type is also set to something specific, like in my example to button?
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 9
- Comments: 53 (22 by maintainers)
Commits related to this issue
- 'react/button-has-type' rule set to off as it is not working with dynamic You can read more about the issue with the rule: https://github.com/yannickcr/eslint-plugin-react/issues/1555 — committed to vrk-kpa/suomifi-ui-components by ketsappi 4 years ago
- refactor(button): refactor into button's own component - disabled eslint for dynamic button type, as stated at: yannickcr/eslint-plugin-react#1555 - creation on button stylesheet - modularization of ... — committed to Classificantes-DH/ibicos-frontend by MaikHenriqueSP 3 years ago
The type should not be dynamic, full stop.
If you want the type to be one of the 1, 2, or 3 options, use if/else and hardcode those three.
Why shouldn’t it be dynamic? Can you explain please?
Stateless React Components should not use JS default values; that needs to be a defaultProp.
@musicMan1337
There is never a need to dynamically specify a Button’s type (and you never ever want a “reset” button, so those two are sufficient).
I think we can agree to disagree on that so I’ll close this issue here. A workaround was mentioned that works just fine. Thanks for all the work on this plugin!
@lydell very true! the ternary case would probably have to be explicitly handled; however, I’d say that the rule should be forcing a single, hardcoded type value - and that you should conditionally render two different elements if you want two types.
Just to add, the above “solution” doesn’t work for TypeScript.
I’m going to just assume I’ll have to disable the rule.
Only twice, since reset buttons are a terrible UX pattern 😃
It shouldn’t be dynamic because all three button types have wildly different semantics - i can’t conceive of when you’d want a submit button randomly changing to be an entirely different kind of button, or vice versa.
A submit button must be inside a form; a regular button must have some kind of javascript behavior - these are different components/elements, not just two flavors of the same thing.
Commonly people create a Button element of which it’s main purpose is to style a button and handle all the different states of the button. This button could then be used in a form with the type ‘submit’. Another use-case would be a button with an onClick handler. This button would need the type ‘button’. I’m pretty sure these two use-cases are spec compliant.
You see, that’s exactly the answer I was afraid would appear any time in this thread.
Many users get confused by the rule. Judging by all your arguments (against “reset” types) the rule should maybe have been named
button-has-correct-typeandcorrectmeans one and foremost “not reset”. All the use cases users presented are basically dismissed by you by asking the users to change their code (into needlessly convoluted if/else structs) just to get rid of the false positive.Responding to valid concerns regarding the usage of a rule should not be countered by “you can fork” or lecturing users on their code.
I am beyond this, as I do currently not work with react anymore but this “you can fork” just sounded rude to me considering all the above constructive feedback on this very opinionated rule.
But then maybe its also not easily possible to change the rule to support dynamic types (“reset” not included) even if the maintainers wanted to.
I agree this rule is handled poorly.
defaultPropswith atypeof eitherbutton,reset, orsubmitshould not trigger.A work-around is to just disable the rule temporarily:
How would using this option be different than simply disabling the rule, or using an override comment? The rule, despite it’s name, does not merely care if your button has a
typeattribute, the point is to assert it’s a correct one - which your option does not ensure.defaultPropswill be deprecated on function components.I have this use case:
At least an opt-in for dynamic assignment would be great. The only option is for me to disable the rule.
@Bram-Zijp sure. and the implementation of that Button element can still use hardcoded
types with an if/else, or, use an eslint override comment.@amannn the other option is to use an if/else with a hardcoded type, which would help ensure you’re using the correct type, and not using reset.
my 2cents on this.
Every decent software engineer should be that concerned with correctness. And no static type analysis or
ASSERTwill prevent invalid input. But I’m afraid this kind attitude is one the reasons there is so many sloppy insecure software released today.On the other hand you did not answer my question if the team would accept a PR with the option to enabled dynamic type assigned for the many reasons voiced and voted here by users of the plugin? The option would default to the current restrictive behaviour but could be relaxed.
I don’t agree; an eslint override comment is the appropriate non-hacky solution to a false positive eslint warning.
I don’t remember @vaske 😕 Maybe I just disabled the rule.
This thread is hilarious. Thanks for all your input @ljharb and contributions to open source, but you are enforcing your opinions on everyone else and saying ‘deal with it’. Eslint is designed to be non-opinionated (unless you are using opinionated plugins/presets) and customisable to the users’ needs. Here you are saying ‘I don’t agree with everyone else so I’m not going to give them the option to do what they need to do, tough luck’.
@pke my response saying to fork was to “eslint is supposed to be unopinionated”, any package can be as opinionated as it wants to - this plugin is opinionated like every other.
I totally agree that changing the rule name would help, but the churn of doing that isn’t worth it.
It’s not at all practical and possible to support dynamic types; that’s just the nature of JavaScript itself (it could be supported in extremely limited ways that would require massive complexity, but that wouldn’t be sufficient for virtually any of the use cases folks have complained about)
If your propType warnings are properly set up to fail your tests, there’s no need to check it in production.
@musicMan1337 you can only defaultProps outside the component. Your statement doesn’t take effect until after the component has been rendered.
@josephshambrook at the least, make a propType that used oneOf, so you’re not just wildly accepting any random string (or worse, “reset”).
Using an override comment inside a component where you’re knowingly violating a best practice is indeed the proper way to handle it.
Yep, I disabled the rule too.
In a REST level 3 kind of app where the app state is completely controlled by the server, the server dictates the fields of a form. That’s a valid scenario for when the button type needs to be dynamic. Since hardcoding the now known button types defeats the entire reason for going REST level 3, which is to have an evolutionary API, which can change in the future without touching the client but just send a new HTML6 value for button type.
But since REST level 3 apps are such a rare breed as of now I’ll just disable this rule that’s supposed to make the button type usage “safe”.
I am also interested in “why” it should be dynamic (because dev typo in props?). Seems weird to duplicate the button three times for a hardcoded value.
@Hypnosphi sure, seems harmless enough, as long as both branches in the ternary were static strings.
@ljharb It can, it will look hacky and it shouldn’t have to considering the legitimacy of use-cases. Perhaps an adding an option to the eslint config which allow for dynamic types would please everyone.
Yep, that’s true. To me that’s more the job of
propTypesor a type system though.Isn’t that true for input types as a whole? Not just specific button? Why wouldn’t this give an error as well?