This blog aims to present a compiled version of some widely accepted writing styles and practices to keep in mind while working with React that should be helpful to both intermediate and experienced developers.
1. Use Object Destructuring: Object destructuring allows you to take specific fields from an object and assign them to a variable instantly. It reduces the number of code lines we need to extract the object properties and makes your code easier to understand. Object destructuring saves a great deal of explicit variable declarations, and it is really useful in situations when:
- Using multiple properties from an object.
- Using the same property multiple times.
Refer to the example below on how to use destructuring for a case where we need to show a user’s details.
2. Props Destructuring: The above approach of object destructuring can also be leveraged while accessing props.
3. Array Destructuring: An often overlooked ES6 feature is array destructuring. It allows us to access array values without specifying indexes.
4. Use Template Literals: Use template literals to build large strings. Avoid using string concatenation. It’s nice and clean.
5. JSX Short Hand: Use JSX shorthand for passing explicit true boolean props to Components. For example, if you want to make your title visible in your NavBar Component:
6. Use Ternary Operators: For cases where we know that we expect only 2 possible options, use ternary operators. Let’s say you want to show a particular user’s details based on role.
The above code causes the equality check to be evaluated 2 times. With ternary, we can lower it to once.
7. Take Advantage of Object Literals: Object literals can help make our code more readable. Let’s say you want to show three types of users based on their roles. Using ternary is not suggested because the number of options is greater than two (it would need nesting). Object literals can be used instead.:
In addition to increasing readability in such scenarios, we can also employ object literals to map dynamic or computed properties.
8. Use Fragments: Always use Fragment over
span as containers. It keeps the code clean and is also beneficial for performance because we are not adding useless containers to the DOM tree, hence one less node is created in the virtual DOM.
9. Don't Define a Function Inside Render: Don’t define a function inside render. Move any JS code out of JSX if that doesn’t serve any purpose of rendering or UI functionality. Try to keep the logic inside render to an absolute minimum.
10. Reusing Expressions with Variables: Declare variables in the block scope code for reusability. As soon as you see the need to use a condition or expression more than once, extract it as a variable instead of repeating the expressions over and over.
11. String Props Don’t Need Curly Braces when being passed to a child component.
12. Lists and the Key prop: The “key” prop is a special string attribute you need to include when rendering lists of elements. React uses keys to uniquely identify items in an array. With keys, React can pinpoint which item has been changed, added, or removed from the array.
Most of the time when rendering arrays, we might tend to use the index as the key. While this sometimes works, using the index as a key can introduce issues especially if the list is expected to change. Consider this list -
const arr = ["item1", "item2", "item3", "item4", "item5"];
Currently, the first list item, “Item1” is at index zero, but if you added another item at the beginning of the list, the “Item1” index would change to 1 which changes the behaviour of your array. Hence make sure to use unique values as keys.
Similarly while using arrow function in JSX-
14. Import Ordering: Always try to import things in the following recommended order. The rule of thumb is to keep the import order like this:
It improves code readability. Most editors like VSCode provide an option to automatically order the imports on file save.
So the example above becomes:
15. File & Folder Structure: One of the most commonly followed files & folder structure is as follows:-
├── /assets - Contains static assets - Icon Svgs, banner images etc.
├── /components - reusable components like navigation bar, buttons, forms
├── /services - JavaSript modules
├── /utils - utilities, helpers, constants.
├── /views/pages - Majority of the app pages would be here
In turn, each component folder should have its respective files grouped under the same. This maintains a consistent hierarchy throughout the codebase. Eg. For the footer component, the necessary files could include-
16. Naming Conventions:
Always use PascalCase for components and camelCase for instances & prop names.
17. Naming Rationales:
Boolean variables, or functions that return a boolean value, should start with “is,” “has” or “should”.
Also, avoid underscores in function names. (
18. Reserved Prop Name Usage: Don’t use DOM component prop names for passing props between components because others might not expect these names.
19. Usage of Quotes: Use double quotes for JSX attributes and single quotes for all other JS.
20. JSX in Parentheses: If the JSX that is being returned by your component or iterator spans more than one line, always wrap it in parentheses.
21. Self-Closing Tags: If your component doesn’t have any children, then use self-closing tags. It improves readability.
The term dangerously is chosen with intention. Using this property can open you up to a cross-site scripting (XSS) attack. So it's highly recommended that the code that gets set is sanitized first. You could either use a custom-written utility to filter out risky code snippets or use external libraries to help with this.
DOMPurify is one good example of this.
23. Using Spread Operator to pass Props: If you have an object, and you want to pass all its keys in JSX, you can use
... as a “spread” syntax to pass the whole object. It helps with avoiding unnecessary object property access & repetition.
24. Using Optional Chaining: Increases readability and simplifies otherwise long logical conjunctions and complex-looking conditions.
25. Shorthand Logic Evaluation: Covering below some examples of cases that return truthy/falsy values that can be relatively shortened.
If using inside JSX, they can be first converted to Boolean using the double negation (!!) operator as:
26. Img Alt prop: Always include an alt prop in your
<img> tags. And, we don’t need to use
alt property because the screen readers already announce
img elements as images.
27. Default Props: It is considered a good practice to set a default value for otherwise optional props.
28. Inline styles: It is not considered good practice to use inline styles in React components. Always make use of options like stylesheets, CSS modules, styled-components, etc.
29. Async/await over Callbacks: Promises & callbacks have been the pillar pattern for working with asynchronous code. However, the introduction of async-await has helped achieve the same functionality, in addition to providing better readability and overcoming certain limitations like issues with nested callbacks (callback hells), etc.
30. Use Error Boundaries: As much as we try to make our application robust, errors are still bound to occur. We create user-friendly UIs to handle such error cases. To guard our app against crashing entirely, React provides the feature of Error boundaries through which we can display a fallback UI should an unexpected error occur. You can make use of React's ErrorBoundary implementation as shown below or use a package like
31. Functional Components over Class components: With the introduction of hooks, there’s practically nothing that you can’t do in Functional components as opposed to class components. And functional components are better because:
● You end up with less code. Also, the resulting translated version is comparatively lesser.
● It gets easier to separate container and presentational components because you need to think more about your component’s state if you don’t have access to setState() in your component.
● The React team recommends them stating they provide a performance boost.
32. Use memoization techniques: Understanding the render cycle of a component can help us in leveraging the various memoization options provided by React to improve the performance of your application and avoid unnecessary re-rendering (especially when dealing with heavy or logically expensive components & computations). Some memoization techniques include:
● React.PureComponent (for class components)
However, we can not go about memoizing every component in our application since even memoization uses memory and can be less performant when used incorrectly. Therefore, the only caveat is knowing whether any such memoization technique is needed or not and when to use which.
Here below is an example of a case when using
memo is beneficial.
ChildComponent should render only once because the value of count has nothing to do with the
ChildComponent. But, it renders each time you click on the button. A better way would be to change
ChildComponent to this: