React best practices and tips that every developer should know. Part 1

Hello, Habr! I present to you the translation of the article "React Best Practices & Tips Every React Developer Should Know Pt. 1" by Alex Devero.



image



React is one of the most popular libraries for building interactive user interfaces. In this article, I will show you some examples of React best practices that will help you become a better developer. Check out these instructions to start writing React code better.



Content:



  1. Keep your components small
  2. Avoid piling up components
  3. Reduce the use of stateful components
  4. Use functional components with hooks and memo instead of components on classes
  5. Do not use props in the original state.


Epilogue: React Best Practices and Tips Every Developer Should Know Part 1



1. Keep your components small



Keeping components small is one of React's best practices that can work wonders. Implementing just this seemingly simple practice can help you write cleaner, more maintainable code. Not to mention that it can help maintain reason, or at least what remains.



There is one proven rule of thumb that you can use. Take a look at the render method. If it has more than 10 lines, then your component is probably too large, and is a good candidate for refactoring and splitting into several smaller components. Remember that one of the ideas for using React, or part of its philosophy, is to reuse code.



The goal is to create pieces of code that you write once, and then use them again and again when you need to. From this point of view, it makes no sense to combine all your data into one massive component, one file. And, even if you really don't care about reusable code, think about it. How easy will components with hundreds of lines of code be in support?



Such a component will be difficult to maintain, debug, and update. It also means that any work with this component will take much longer. In other words, your overall performance will suffer. And sooner or later it will drive you crazy. Or it will drive your teammates and colleagues crazy, and they will start to drive you crazy.



Whatever you choose, you will soon lose your mind and perhaps make enemies for yourself. It's not worth it. Keep your components small. Keep friendships, sanity, time, and productivity. Simplify debugging, updating, and maintaining code. Consider one example.



It was



/// // file: index.jsx import React from 'react' const books = [ { category: 'Business', price: '$20.00', name: 'Private Empires', author: 'Steve Coll' }, { category: 'Philosophy', price: '$25.00', name: 'The Daily Stoic', author: 'Ryan Holiday' }, { category: 'Sport', price: '$15.95', name: 'Moneyball', author: 'Michael Lewis' }, { category: 'Biography', price: '$21.00', name: 'Titan', author: 'Ron Chernow' }, { category: 'Business', price: '$29.99', name: 'The Hard Thing About Hard Things', author: 'Ben Horowitz' }, { category: 'Fiction', price: '$4.81', name: 'Limitless: A Novel', author: 'Alan Glynn' } ] class Bookshelf extends React.Component { render() { const tableRows = [] this.props.books.forEach((book) => { tableRows.push( <tr> <td>{book.name}</td> <td>{book.author}</td> <td>{book.price}</td> <td>{book.category}</td> </tr> ) }) return ( <div> <form> <input type="text" placeholder="Search..." /> <button>Search</button> </form> <table> <thead> <tr> <th>Name</th> <th>Author</th> <th>Price</th> <th>Category</th> </tr> </thead> <tbody>{tableRows}</tbody> </table> </div> ) } } // Render Bookshelf component ReactDOM.render(<Bookshelf books={booksData} />, document.getElementById('container'))
      
      





Has become



 /// // file: books-data.js const books = [ { category: 'Business', price: '$20.00', name: 'Private Empires', author: 'Steve Coll' }, { category: 'Philosophy', price: '$25.00', name: 'The Daily Stoic', author: 'Ryan Holiday' }, { category: 'Sport', price: '$15.95', name: 'Moneyball', author: 'Michael Lewis' }, { category: 'Biography', price: '$21.00', name: 'Titan', author: 'Ron Chernow' }, { category: 'Business', price: '$29.99', name: 'The Hard Thing About Hard Things', author: 'Ben Horowitz' }, { category: 'Fiction', price: '$4.81', name: 'Limitless: A Novel', author: 'Alan Glynn' } ] export default booksData /// // file: components/books-table.jsx import React from 'react' class BooksTable extends React.Component { render() { const tableRows = [] this.props.books.forEach((book) => { tableRows.push( <tr> <td>{book.name}</td> <td>{book.author}</td> <td>{book.price}</td> <td>{book.category}</td> </tr> ) }) return ( <table> <thead> <tr> <th>Name</th> <th>Author</th> <th>Price</th> <th>Category</th> </tr> </thead> <tbody>{tableRows}</tbody> </table> ) } } export default BooksTable /// // file: components/search-bar.jsx import React from 'react' class SearchBar extends React.Component { render() { return ( <form> <input type="text" placeholder="Search..." /> <button>Search</button> </form> ) } } export default SearchBar /// // file: components/bookshelf.jsx import React from 'react' // Import components import BooksTable from './components/books-table' import SearchBar from './components/search-bar' class Bookshelf extends React.Component { render() { return ( <div> <SearchBar /> <BooksTable books={this.props.books} /> </div> ) } } export default Bookshelf /// // file: index.jsx import React from 'react' // Import components import Bookshelf from './components/bookshelf // Import data import booksData from './books-data' // Render Bookshelf component ReactDOM.render(<Bookshelf books={booksData} />, document.getElementById('container'))
      
      





2. Avoid piling up components



Each rule should be applied with caution. This also applies to these React best practices, especially the previous one. When it comes to components, it’s very easy to overdo it and write even the smallest pieces of code in the form of components. Do not do this. It makes no sense to make each paragraph, span or div a component.

Think before you begin to divide each component into small parts. You can think of the component as a mixture of “HTML”, which does only one thing, being independent, and the user will perceive it as a whole. Does it make sense to make this piece of code a component? If not, combine this code. Otherwise, split it.



Let's look at some examples to illustrate this definition of a component. One example is modal dialogue. This component can consist of many small elements, such as divs, headings, paragraphs of text, buttons, etc. Theoretically, all of these elements can be distinguished into small components.



In practice, this is pointless. Yes, some of these elements can exist independently of each other. However, is it really useful to create a component consisting of only one paragraph or one heading? What will happen next? Component for label, input or even span? This approach is not sustainable.



Fortunately, there is another way to look at this. You can use the atomic design methodology as a guide. In atomic design, everything is divided into six categories: atoms, molecules, organisms, templates, pages, and utilities. You start with the smallest elements, such as buttons, links, shortcuts, inputs, etc. These are atoms.



Then you combine the atoms and create the molecules. Examples of molecules can be a modal dialog, form, pop-up window, drop-down menu, navigation, etc. Further, you can combine one molecule with another or with an atom and create an organism. An example of an organism is a heading, a list of products, or a shopping basket. Templates, pages and utilities are no longer important.



How to combine atomic design with these two examples of best practices in the field of React components? Let's not complicate. A component can be anything more than an atom, i.e. molecule, organism, or even a template or page, if taken to the limit. In this sense, the label, heading, paragraph are not components, because they are atoms.

However, modal dialogs, forms, pop-ups, drop-down lists, etc. are components, since they all relate either to molecules or to the category of an organism. There are still some dubious elements, such as a button. Yes, from the point of view of atomic construction it is an atom. However, it can exist independently, in many variations, and still work.



In such cases, I suggest not thinking about React’s best practices, and just be guided by my own inner instincts. In the end, it is you who will work with the code. The important thing is that you are comfortable. So don’t just blindly follow some list of best practices. And if you work in a team? Share your thoughts on this with your colleagues.



3. Reduce the use of stateful components



This is one of the best React practices that has been applied for some time. However, this practice has become more popular with the advent of React 16.8.0 and React hooks. Before that, when you wanted to use state or any life cycle method, you also had to use a stateful component. There was no other way.



Hooks changed that. After they were officially unveiled, React developers were no longer limited to stateful components because they needed to use state. Thanks to hooks, React developers can now write stateless components using state and even life cycle methods as they wish.



Why is it important? Stateless or functional components are generally better than stateful components when it comes to performance. The reason is that there is no state, no life cycle methods. In other words, less code to execute as well as transpiling. Of course, this difference can be barely noticeable, almost invisible, if you are working on some very small project.



However, these small differences may add up as your project grows. Also think about how many lines of code a stateful component needs compared to functional. The functionality is also shorter and often easier to read. Let's look at the button component, defined as a component with state control and functions. Which one do you like more?



 // Button defined as a stateful component class Button extends React.Component { handleClick = () => { // Do something } render() { return( <button type="button" onClick={this.handleClick}>Click me</button> ) } } // Button defined as a functional component const Button = () => { const handleClick = () => { // Do something } return( <button type="button" onClick={handleClick}>Click me</button> ) }
      
      





4. Use functional components with hooks and memo instead of components on classes



As we already discussed, you no longer need to use stateful components just to use state. Moreover, some React developers also believe that in the future, React will begin to move away from classes. Is this true, now it does not matter. The important thing is that one functional component can now use state thanks to hooks.

And secondly, the use of functional components has its advantages. TLDR? No class, inheritance and constructor. There is no this keyword. Strict React Best Practices. High signal to noise ratio. Swollen components and bad data structures are easier to spot. The code is easier to understand and verify. And, again, performance is better.



And something else. Many React developers opposed functional components. One of the problems is that you, as a React developer, cannot control the rendering process when using the functional component. When something changes, React returns a functional component, regardless of whether the component itself has been changed.

In the past, the solution was to use a pure component. The clean component provides the ability to compare state and props. This means that React can “check” whether the contents of the component, props, or the component itself have changed. If so, he will return it. Otherwise, it will skip re-rendering and will reuse the last rendered result. Less rendering equals better performance.

With React 16.6.0, this is no longer a problem, and the argument against functional components is no longer valid. What changed the game was memo. Memo brought a shallow comparison with a functional component, the ability to “check” whether the content of the component, props or the component itself has changed.



Again, based on this comparison, React will either return the component back or reuse the result of the last rendering. In short, memo allows you to create “clean” functional components. There is no longer any reason to use statefull components, or pure components. At least if you do not need to cope with a difficult condition.



In this case, you should consider using something more scalable and manageable, such as MobX, Redux, or Flux, instead of the state of the components. Another possible option would be to use context. In any case, thanks to hooks and memo, functional components are certainly some of the best React practices worth thinking about.



5. Do not use props in the original state



This is one of the React best practices that I would like to know about when I started learning. Then I did not know that it was a very bad idea to use props in the initial state. Why is this a bad idea? The problem is that the constructor is called only once during component creation.



This means that when you make some changes to the props next time, the state of the components will not be updated. It will retain its former meaning. Then I mistakenly assumed that the props are synchronized with the state. Thus, when some details change, the state will change to reflect this change. Unfortunately, it is not.



This might not be a problem if you want the state to receive values ​​from props only once during the initial rendering, and you would control the state inside the component. Otherwise, you can solve this problem with componentDidUpdate. As the name says, this lifecycle method allows you to update a component when something changes, such as props.



If you decide to use this method, remember one thing. It will not be involved in the initial rendering, but only in the next. Therefore, be sure to initialize the state of the component with the necessary values, possibly obtained from props. Then use componentDidUpdate to update these values ​​and the component as needed.



Epilogue: React Best Practices and Tips Every Developer Should Know Part 1



Congratulations! You have just finished the first part of this mini-series of articles about React's best practices. Today, you’ve learned about five practices you can use to make React code shorter, simpler, better, faster, and easier to read and maintain. Now it is up to you to implement the practice with which you agree and begin to use it.



In the next part, you'll learn about another set of best practices and tips to help you improve your React code, as well as your programming skills. Until then, take what you learned today and spend some of your time practicing.



If you liked this article, then please subscribe.



Originally posted to the Alex Devero Blog.



All Articles