In this article, we'll see some of the common mistakes made by React developers and ways to avoid them.
So let's get started.
Don't Forget that Every Route Change Mounts and Unmounts a Component
Whenever we're using routing in React application, we declare routes inside the Switch
component so at a time only one component with the matching route is displayed.
Therefore, whenever we go from one route to another, the previously displayed component is unmounted and the component with the new matching route is mounted.
If you need to persist some data across route change, you need to declare it in the component which encapsulates the routes such as the App
component in the following Code Sandbox or some other way of persisting data like using local storage or session storage
As you can see in the above Code Sandbox, whenever we change the route by clicking on the links, we get the corresponding console.log
displayed on the console to indicate that the previous component is unmounted and a new component is mounted.
Don't Use the Wrong setState Syntax
Whenever we declare a state inside the class-based component, it's always an object like this:
this.state = {
counter: 0
}
so whenever we use the updater form of setState syntax to update the state, it looks like this:
this.setState((prevState) => {
return {
counter: prevState.counter + 1
};
});
As the state is an object, prevState
is also an object so we access the counter
using prevState.counter
.
But when we're using functional component using React Hooks the state can be an object or a non-object value as shown below:
const [counter, setCounter] = useState(0);
Here, the value of counter
is not an object but it's a number so to update the state using updater syntax we write the code like this:
setCounter((prevCounter) => prevCounter + 1);
Here, the prevCounter
is a number so we don't use prevCounter.counter
but just prevCounter
or it can be simplified as shown below:
setCounter((counter) => counter + 1);
Check out my this article for complete introduction to React State
Don't Call Hooks from Class Components
Starting with React version 16.8.0, React has introduced Hooks that allow us to write better React code
and make use of state and component life cycle methods inside functional components.
Check out my this article for an Introduction to React Hooks.
To make coding easy, there are many hooks provided by React like:
-
useParams
hook to access URL parameters when using React Routing -
useHistory
hook to get access to history API inside any component -
useRef
hook to get access to DOM element
and many other hooks.
But all of these hooks which usually starts with the use
keyword work only inside the functional components.
If you're having a class-based component then you can't use these hooks. You need to refactor your code to convert it to functional components otherwise, you might get an error as can be seen in the below screenshot:
Don't Forget to Add a Key Prop When Using the Array map Method
Take a look at this Code Sandbox Demo.
Here, for displaying a list of items, we're using the following code:
const Items = ({ items }) => (
<ol>
{items.map((item) => (
<Item item={item} />
))}
</ol>
);
In React, for displaying a list of items stored in an array, usually, the array map
method is used.
But as soon as you add an item to the list in the above Code Sandbox, you will see a missing key warning displayed in the console.
This is because every time you're using the array map
method to loop over the items, you need to provide a unique key
prop which React uses to identify which elements on the screen need to be re-rendered and adding key
prop helps to avoids unnecessary re-rendering in your app.
Here's an updated Code Sandbox Demo with the added key
prop.
Here, we've provided a unique key
prop to each element we're looping over like this:
<Item item={item} key={index} />
Therefore, If you try adding some items, you will not get any warning in the console.
Note: In the above code, as the elements not re-ordered or removed, using
index
askey
works fine but If you're removing or changing the displayed elements order then you need to provide a unique key instead of usingindex
.
Don't Use Inline Functions the Wrong Way
Take a look at this Code Sandbox Demo.
Here, we've added some items to the state:
const [items, setItems] = useState(["one", "two"]);
and we're looping over them to display on the screen:
{items.map((item, index) => (
<li key={index}>
{item} <button onClick={handleRemoveItem(item)}>Remove</button>
</li>
))}
If you check the application, you will see that no items are displayed on the screen and adding new items also does not work as can be seen below:
This is because of the onClick
handler for the button:
<button onClick={handleRemoveItem(item)}>Remove</button>
Here, we're calling the handleRemoveItem
method when the user clicks on the button but the way we're calling the method is wrong.
So If we don't need to pass any parameter we use the following syntax:
<button onClick={handleRemoveItem}>Remove</button>
But later If we decide to pass some parameter to the function, we need to call the handler inside inline function like this:
<button onClick={() => handleRemoveItem(item)}>Remove</button>
Most React developers forget to add an inline function and then it takes hours of debugging to understand why something does not work.
Here's an updated working Code Sandbox Demo.
Thanks for reading!
Starting with ES6, there are many useful additions to JavaScript like:
- ES6 Destructuring
- Import and Export Syntax
- Arrow functions
- Promises
- Async/await
- Optional chaining operator and a lot more.
You can learn everything about all the ES6+ features in detail in my Mastering Modern JavaScript book.
Check out free preview contents of the book here.
Also, you can check out my free Introduction to React Router course to learn React Router from scratch.
Want to stay up to date with regular content regarding JavaScript, React, Node.js? Follow me on LinkedIn.