The Most Common Errors On React.js That You Might Possibly Do!
Inspired by the read articles on the medium, we decided to write my article and tell you how to avoid the most common mistakes in your React application and what it’s for.
We tried to explain as much as possible every mistake, therefore, our article is more focused on young developers who are still in search of new knowledge. Although it seems to us, an experienced developer can find for himself a couple of interesting things in this article.
In brackets before each paragraph, I left a reference to the eslint rule. You can later find them on GitHub and add them to your project.
(react/forbid-component-props)
The first common mistake is to pass ‘style’ and ‘className’ as props to your component. Avoid this, since you will add a lot of complexity to your components.
Instead, you can use the ‘classnames‘ library and add interesting variations to your component (if you use CSS classes):
const { hasError, hasBorder } = this.props; const componentClasses = classnames({ 'your-component-main-class': true, 'your-component-main-class_with-error': hasError, 'your-component-main-class_with-border': hasBorder, });
(react/forbid-prop-types)
The following error is not informative propTypes. Do not use PropTypes.any, PropTypes.array, and PropTypes.object. Describe your props as much as possible. This will allow you to leave good documentation for the future, and you (or another developer) still say many thanks to you.
class MyComponent extends React.Component { static propTypes = { user: PropTypes.shape({ id: PropTypes.number, name: PropTypes.string, }), policies: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.number, type: PropTypes.string, value: PropTypes.string, }), } }
(react/forbid-foreign-prop-types)
Let’s continue with propTypes. Do not use the propTypes of another component:
import SomeComponent from './SomeComponent'; SomeComponent.propTypes;
Create a file in which you will keep in order for your global propTypes:
import { userShape, policiesArray } from '../common/global_prop_types';
This will help babel-plugin-transform-react-remove-prop-types remove propTypes from the production code and make your offer a little easier.
(react/no-access-state-in-setstate)
The following error is very interesting:
class MyComponent extends React.Component { state = { counter: 1, }; incrementCounter = () => this.setState({ counter: this.state.counter++ }); massIncrement = () => { // this code will lead to not what you expect this.incrementCounter(); this.incrementCounter(); } }
Because setState is an asynchronous state function, the state in both cases will be the same and this.state.counter will be 1 and we get:
incrementCounter = () => this.setState({ counter: 1++ }); incrementCounter = () => this.setState({ counter: 1++ });
In order to avoid this, you can use setState callback which takes as an argument the past state:
incrementCounter = () => this.setState((prevState) => ({ counter: prevState.counter++ }));
(react/no-array-index-key)
This error is also very common, therefore, read carefully and avoid it in the future:
users.map((user, index) => ( <UserComponent {...user} key={index} /> ));
React uses prop key as a reference to the DOM element, and it helps it to quickly find and render the right component (all of course, more complicated, but we simplified it on purpose).
What happens if you add a new user to the middle of the array? React will be forced to re-render all UserComponents after the new one is added since the index will be changed for a large number of components. Use unique keys instead. A very simple way out is the id that you get from your database:
users.map((user) => ( <UserComponent {...user} key={user.id} /> ));
(react/no-did-mount-set-state), (react/no-did-update-set-state)
This error is also very common in my practice. If you try to update state in componentDidUpdate or componentDidMount methods, you will get an infinite loop of the re-rendered. React starts checking for the re-rendered when the component changes state or props. If you change state after the component is down-scaled in DOM or has already been updated, you run the test again and again and again …
(react/no-direct-mutation-state)
Mutation state is a very big mistake. An uncontrolled state mutation will lead to undetectable bugs and, as a consequence, to big problems. My personal opinion is the use of immutable-js, like a library that adds immune structures. And you can use them with Redux/MobX/Any state management library. You can also use deepClone from lodash to clone state and then clone mutation or use the new JS feature – destructuring:
updateStateWrong = () => this.state.imRambo = true; updateStateRight = () => { const clonedState = cloneDeep(this.state); clonedState.imAGoodMan = true; this.setState(clonedState); } updateWithImmutabelJS = () => { const newState = this.state.set('iUseImmutableStructure', true); this.setState(newState); } updateWithDestructuring = () => this.setState({ ...this.state, iUseDestructuring: true });
(react/prefer-stateless-function)
This rule describes more improvements to your code and application than error, but we still recommend that you follow this rule. If your component does not use state, make it a stateless component (we like the term ‘pure component’ more):
class MyComponentWithoutState extends React.Component { render() { return <div>I like to write a lot of unneeded code</div> } } const MyPureComponent = (props) => <div>Less code === less support</div>
(react/prop-types)
Please always add a check for the types of props (propTypes) if your component receives props. Think of it as documenting your code. You will say to yourself again and again for this. PropTypes will help you understand and understand what your component can render, as well as what it needs for rendering.
MyPureComponent.propTypes = { id: PropTypes.number.isRequired, // And I know that without id component will not render at all, and this is good. }
(react/jsx-no-bind)
A very common and big mistake that I’ve seen in code many times. Do not Use Bind And Arrow Function In Jsx. Never. More.
The hottest place in hell is waiting for someone who writes .bind (this) in JSX.
Every time the component is rendered, your function will be recreated, and this can severely slow down your application (this is due to the fact that garbage collector will have to run much more often). Instead of .bind (this), you can use Arrow functions in a certain way:
class RightWayToCallFunctionsInRender extends React.Component { handleDivClick = (event) => event; render() { return <div onClick={this.handleDivClick} /> } } const handleDivClick = (event) => event; const AndInPureComponent = () => { return <div onClick={handleDivClick} /> }
(react/jsx-no-target-blank)
Security-related error. It seems very strange to us that people still make this mistake. A lot of people wrote a lot of articles on this topic in 2017.
If you create a link with the target = ‘_ blank’ attribute, do not forget to add rel = ‘noreferrer noopener’ to it. Very simple:
<a href="https://example.com" target="_blank" rel="noreferrer noopener" />
Conclusion
This is all we would like to tell you about the React.js. we will be very grateful if leave us your feedback and share in it your opinion on the problems that we have described in this article.