ESLint is giving me this error on a react project.
ESLint - Component should be written as a pure function (react prefer/stateless function)
It poi
Add constructor() like:
exports class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>Hello</div>
);
}
}
Write your component as a stateless function:
export myComponent = () => { //stuff here };
There are actually two styles of defining components in React: Functional components (which are just functions from props to a React component) and class components.
The main difference between them is that class components can have state
and lifecycle methods such as componentDidMount
, componentDidUpdate
, etc.
Whenever you don't need state of lifecycle methods, you should write your component as a stateless function, as stateless components are in general easier to reason about.
To write a functional component, you write a function that takes a single argument. This argument will receive the component's props. Consequently, you don't use this.props
to access the component's props - you just use the function's argument.
If you rely on props
, then there is a better (somewhat arguable, as of this writing) way to fix this error without writing out Stateless functions - by writing a PureComponent and using this eslint rule [source]:
"react/prefer-stateless-function": [2, { "ignorePureComponents": true }],
With above rule, the following snippet is valid (since it depends on props
)
class Foo extends React.PureComponent {
render() {
return <div>{this.props.foo}</div>;
}
}
React team plans to build optimizations around SFC but they are not there yet. So until that happens, SFCs
will not offer any benefits over PureComponents
. In fact, they will be slightly worse as they will not prevent wasteful renders.
export class myComponent extends PureComponent {
...
}
Two choices.
Temporarily disable warning
(Untested; and there are multiple ways to do this.)
// eslint-disable-next-line react/prefer-stateless-function
export class myComponent extends React.Component {
...
}
Use a pure stateless component
The return value is what will be rendered (e.g., you're basically writing class-based component's render
method:
export const myComponent = () => {
return (
// JSX here
)
}
(Or use non-ES6 notation if that's your thing.)
For components like this with no other supporting logic I prefer the implicit return, e.g.,
export MyComponent = () =>
<div>
// Stuff here
</div>
This is a matter of preference. I would say that you should follow React naming conventions, though, and keep all components starting with an upper-case letter.
ESLint may complain about missing parens around a multi-line JSX expressions, so disable that rule or use parens.
If you need props, they're passed in as the argument to the function:
const MyComponent = (props) =>
<div>
<Something someProp={props.foo} />
</div>
export MyComponent
And you can destructure in the parameter as usual for convenience:
const MyComponent = ({ foo }) =>
<div>
<Something someProp={foo} />
</div>
This can make the implicit return a little easier if you were using local vars. You'll get an ESLint warning about missing PropTypes
unless you declare them; since it's not a class you cannot simply use static propTypes
in the class, they must be attached to the function (which many people prefer anyway).
const myComponent = () => {
return (
//stuff here
);
};
export default myComponent;
And in app.js file just import this component as we do for class like
import myComponent from './myComponent.js'
and call as
<myComponent />
It will work for sure.