DEV Community

Cover image for Part 4: Writing Clean and Efficient React Code- Best Practices and Optimization Techniques

Part 4: Writing Clean and Efficient React Code- Best Practices and Optimization Techniques

Sathish Kumar N on June 18, 2023

Welcome to Part 4 of our series on "React best practices in 2023"! In this part, we will explore various techniques and strategies to write clean a...
Collapse
 
pengeszikra profile image
Peter Vivo

Instead of use prop types use typescript with FC

import {FC} from 'react';

interface Button {
  text:string;
  enabled:boolean;
}

const Button:FC<Button> = ({ text, enabled }) => (
  <button enabled>{text}</button>
);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
sathishskdev profile image
Sathish Kumar N

Thank you for your suggestion!

If you are using JavaScript (without TypeScript), you can continue using prop-types to validate the props in your components.

If you are using TypeScript, you can benefit from the additional type-checking capabilities it offers by using the FC type to define your components' props.

Collapse
 
pengeszikra profile image
Peter Vivo

Does not have any reason to not use TS.

Collapse
 
merri profile image
Vesa Piittinen • Edited

But you don't need FC.

import type { ReactNode } from 'react';

interface Props {
  children: ReactNode;
  enabled: boolean;
}

export const Button = ({ children, enabled = true }: Props) => (
  <button aria-disabled={!enabled || undefined}>{children}</button>
);

// or

export function Button({ children, enabled = true }: Props) {
  return (
    <button aria-disabled={!enabled || undefined}>{children}</button>
  );
}

// or
import { forwardRef } from 'react';

export const Button = forwardRef<HTMLButtonElement, Props>(function Button(
  { children, enabled = true),
  ref
) {
  return (
    <button ref={ref} aria-disabled={!enabled || undefined}>{children}</button>
  );
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
leocaprile profile image
Matías Fuentes

FC is a unnecessary import, you can destructure the props as the examples below

Collapse
 
r4dic4l profile image
Oana Maria Teodorescu

There's a small mistake in no. 10: Shorthand for boolean props, should be multiSelect={true} replaced by multiSelect prop instead of multiSelect={false}.

Image description

Collapse
 
sathishskdev profile image
Sathish Kumar N • Edited

Thank you for bringing the issue!

I updated the snippet now.

Collapse
 
brense profile image
Rense Bakker

I think you're mistaken between named exports and named functions. If you write your components like this:

export default function MyNamedFunctionComponent(){
}
Enter fullscreen mode Exit fullscreen mode

Your editor has no trouble finding out what you mean when you try to use MyNamedFunctionComponent.

The same goes for variables like this:

const MyNamedConponent(){}
export default MyNamedConponent
Enter fullscreen mode Exit fullscreen mode

What you DONT want to do is:

// Code smell anonymous default export...
export default function(){}
Enter fullscreen mode Exit fullscreen mode

And infact recommended react eslint rules will warn you not to do that.

I'm also quite unsure if your tree shaking claim is true... If it is true it would only be for webpack 3 maybe. I'm definitely not seeing "use default exports" on this checklist: smashingmagazine.com/2021/05/tree-...

Collapse
 
sathishskdev profile image
Sathish Kumar N • Edited

I apologize for any confusion caused in my blog.

I am familiar with the concept of named and default exports. Please refer to the following code snippet to understand the difference between default and named exports:

// ✅ Use named export
export function MyNamedFunctionComponent() {
  // Component logic...
}

// ❌ Avoid default export
export default function MyComponent() {
  // Component logic...
}
Enter fullscreen mode Exit fullscreen mode

In the case of default exports, refactoring can be more challenging. Here's an example:

Default export:

// In Component
export default function MyComponent() {...}

// When importing in the first component
import component from "./MyComponent"

// When importing in another component
import myComponent from "./MyComponent"
Enter fullscreen mode Exit fullscreen mode

However, when using named exports, this confusion can be avoided.

Regarding the claim about tree shaking, it's important to note that tree shaking itself is not directly dependent on the use of default exports.

By utilizing named exports, you gain more control over the exported values. This allows unused values to be eliminated during the bundling process, resulting in a smaller bundle size.

Collapse
 
brense profile image
Info Comment hidden by post author - thread only accessible via permalink
Rense Bakker

Named exports are objects though. If you have one file, with several named exports, in the background, it just looks like a big object to the bundler and all that code will be included, even if you only use one of the named exports in your code. That is exactly why some libraries recommend you use their default exports and NOT their named exports, because the named exports are all exported from a single index.ts file.

If you really want to be religious about optimizing for tree shaking, it doesnt matter what kind of export you use, named or default. The only rule is: export one thing per file. In reality though, it doesnt matter that much. If you have some utils file with a bunch of named exports, it doesnt matter that they all get included in the bundle, because the overhead of some small functions is minimal.

 
sathishskdev profile image
Info Comment hidden by post author - thread only accessible via permalink
Sathish Kumar N • Edited

I agree your point!

In Tree shaking, the key is to import only the specific exports you need, whether they are named or default exports.

When we using default exports, we don't need to specify a specific name when importing that value into another file. You can give it any name you want when you import it.

 
brense profile image
Info Comment hidden by post author - thread only accessible via permalink
Rense Bakker

You are ChatGPT :P

 
sathishskdev profile image
Info Comment hidden by post author - thread only accessible via permalink
Sathish Kumar N

I didn't use ChatGPT for my comments!

Collapse
 
sney profile image
Snehil

Are you using chat gpt for your replies haha? Same tone of voice..

Thread Thread
 
sathishskdev profile image
Sathish Kumar N • Edited

Ha ha! I am using Quillbot to convert my sentence and improve it further.

Collapse
 
insidewhy profile image
insidewhy • Edited

I wonder, why do you write all your exports at the bottom?

  1. You have to type every exported declaration name twice, which is usually a lot more characters than typing export next to each exported declaration.
  2. Whether a declaration is exported or not is extremely important information, I shouldn't have to scroll to the bottom of the file before I find out whether something is exported or not.
Collapse
 
borobudur01 profile image
borobudur01

Excellents points. I agree with all of them.
About How you "Avoid huge component" I believe what you do with your components is just as bad if not worse tho. The modularity is too extreme and at the end, it's a nightmare to work with.

Collapse
 
nvrtmd profile image
yuza • Edited

Hello,

I thoroughly enjoyed reading your React Best Practices in 2023 series. I'm a developer from South Korea, and I'm interested in translating the four articles included in your React Best Practices in 2023 series into Korean. I would like to post them on my personal blog with proper attribution and links. Would that be possible? I believe it would make it more convenient for Korean developers to access your content. Looking forward to your response :) Have a great day!

Collapse
 
silverium profile image
Soldeplata Saketos

React.memo is less performant than just rendering the component again. Under the hood, the memo function has more operations than rendering a simple component

Some comments have been hidden by the post's author - find out more