eslint-plugin-react: react/prefer-stateless-function false positive
Input
class Test extends React.Component {
constructor() {
super();
this.dispatchThingViaRedux = () => this.props.dispatch(thing());
}
render() {
return <button onClick={this.dispatchThingViaRedux}>Click me!</button>;
}
}
This gives a lint error to prefer a stateless function. However, in this case, it is not appropriate. While you could make a stateless function and just create a dispatch function every time, the value for the button onClick handler is changed between updates (i.e. newProps.onClick. !== props.onClick). Hence DOM updates have to occur if a stateless function was used.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 29 (15 by maintainers)
I’ve run into some false positives with classes that make use of
onClickoronSubmithandlers to avoid recreating functions insiderender. For example:While all the data is coming from props, I can’t see any way it could be rewritten as a stateless function without breaking the
jsx-no-bindrule.Following @ljharb advice’s I rewrote the rule and it should now better target the components that should be written as SFC.
The new version will ask you to write a component as a SFC if:
displayName,propTypes,renderand/or useless constructor (same detection as ESLintno-useless-constructorrule)this.propsand/orthis.context(destructuring is handled)render()never returns anything than JSX (should cover all falsy values)I also added much more tests.
Let me know I missed something.
@Robinnnnn
@Kerumen decorators are just functions so your code is equivalent to:
I’m not sure what your HOC does but technically it should be possible for Button to be a SFC like so:
Things that should disqualify a component from being an SFC in this linter rule:
thisbesidesthis.propsorconst { props } = thisreturn nullinrender()In other words, a class-based component should only be an SFC when:
rendermethod (ignoring useless constructors)this.propsrender()never returnsnull(orfalseorundefinedorreturn;orreturn '';)Just double-checked about those stateless components and you guys are right, they aren’t pure. My world just shattered 😢
Thank you!!
@Robinnnnn It’s
mapStateToProps- the stateless function receives props, not state - the store’s state is what is being mapped. You absolutely can (and should) convertMyComponentto an SFC.@artisologic That would still re-create
_handleClickeveryrender. To quote the description of thejsx-no-bindrule:So even if the code doesn’t trigger
jsx-no-bind, the performance penalty from creating functions insiderenderstill exists.As a side note, I like to use the
no-use-before-definerule because I feel hoisting adds unnecessary complication, and breaks the top-to-bottom flow of logic in a file. Additionally, stateless components currently don’t support pure render /shouldComponentUpdate(Before now I assumed they were already pure by nature of being functional, but it appears I was wrong about that).