DEV Community

Cover image for These Mistakes Are Breaking Your Projects!
RG Global x htmllessons
RG Global x htmllessons

Posted on

These Mistakes Are Breaking Your Projects!

These 10 coding mistakes are silently ruining your codebase. Learn how to fix them before they break your frontend and backend forever.

1. Move business logic to services

Bad approach:

const calculateTotal = (products) => {
  return products.reduce((acc, product) => acc + product.price, 0)
}

const ShoppingCart = ({ products }) => {
  const total = calculateTotal(products)
  return <div>Total: {total}</div>
}
Enter fullscreen mode Exit fullscreen mode

Good approach:

class CartService {
  calculateTotal(products) {
    return products.reduce((acc, product) => acc + product.price, 0)
  }
}

export const cartService = new CartService()

export const ShoppingCart = ({ products }) => {
  const total = cartService.calculateTotal(products)
  return <div>Total: {total}</div>
}
Enter fullscreen mode Exit fullscreen mode

2. Use constants and enums

Bad approach:

if (status === 'SUCCESS') {
  // handle success
}
Enter fullscreen mode Exit fullscreen mode

Good approach:

export const STATUSES = {
  SUCCESS: 'SUCCESS',
  ERROR: 'ERROR',
  PENDING: 'PENDING'
}

if (status === STATUSES.SUCCESS) {
}
Enter fullscreen mode Exit fullscreen mode

3. Create configs (for example, for pages)

Talk about how the subscription will disappear this month, and that you're currently buying a subscription with everything included. Also about the upcoming intensive course on Next.js 15

Bad approach:

import Link from 'next/link'

const Navigation = () => {
  return (
    <Link href='/contact'>
      Contact
    </Link>
  )
}

export default Navigation
Enter fullscreen mode Exit fullscreen mode

Good approach:

class PageConfig {
  home = '/'
  about = '/about'
  contact = '/contact'
}

export const pageConfig = new PageConfig()

import Link from 'next/link'
import { pageConfig } from '../config/pages.config'

const Navigation = () => {
  return (
    <Link href={pageConfig.contact}>
      Contact
    </Link>
  )
}

export default Navigation
Enter fullscreen mode Exit fullscreen mode

4. Properly import modules for better optimization

When we import only what we need from a library, our app becomes smaller and faster. Imagine it like packing only the tools you'll actually use for a trip instead of your entire toolbox.

Bad approach:

import _ from 'lodash'
const sortedArray = _.sortBy(array, 'property')
Enter fullscreen mode Exit fullscreen mode

Good approach:

import sortBy from 'lodash/sortBy'
const sortedArray = sortBy(array, 'property')
Enter fullscreen mode Exit fullscreen mode

5. Use dynamic imports (SSR vs SSR false)

Dynamic imports let us load parts of our app only when they're needed. This makes the initial page load much faster because the browser doesn't have to download everything at once.

It's also important to lazy load only those elements that aren't needed by the user at the initial stage.

Example:

import dynamic from 'next/dynamic'

const ClientOnlyComponent = dynamic(
  () => import('../components/ClientOnlyComponent'),
  { ssr: false }
)

const LazyLoadedComponent = dynamic(
  () => import('../components/LazyLoadedComponent')
)

const MyPage = () => {
  return (
    <div>
      <h1>My Page</h1>
      <p>This page demonstrates dynamic imports with and without SSR.</p>
      <ClientOnlyComponent />
      <LazyLoadedComponent />
    </div>
  )
}

export default MyPage
Enter fullscreen mode Exit fullscreen mode

6. Import dependencies at the moment of use

This is like calling a friend only when you actually need their help, instead of making them wait with you all day. Load packages only when a user takes an action that requires them.

Bad approach:

import { toast } from 'react-hot-toast'

const handleClick = () => {
  toast('Hello, world!')
}
Enter fullscreen mode Exit fullscreen mode

Good approach:

const handleClick = async () => {
  const { toast } = await import('react-hot-toast')
  toast('Hello, world!')
}
Enter fullscreen mode Exit fullscreen mode

7. Move dependencies to devDependencies

Some packages are only needed when you're building your app, not when users are using it. By putting these in devDependencies, you make your final app smaller and faster to load.

We move dependencies to devDependencies so they are installed only in the development environment, not in production, thereby reducing the final build size and speeding up installation on the server.

package.json:

{
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  },
  "devDependencies": {
    "eslint": "^7.32.0",
    "webpack": "^5.58.2"
  }
}
Enter fullscreen mode Exit fullscreen mode

8. Be careful with SSR usage

SSR (Server-Side Rendering) is worse than ISR (Incremental Static Regeneration) from an optimization perspective because SSR generates a page on the server for each request, which increases load and slows down response time. As traffic increases, server costs grow since 1 request gets 1 response. ISR, on the other hand, generates a page once and updates it on a schedule, reducing server load and speeding up content delivery.

During editing, you can show SSR and ISR and the difference in data retrieval, in one case 1 request 1 response, and in the other 1000 or more requests and still 1 response (which is super optimized)

9. Optimize classes with tailwind-merge

When working with CSS classes in Tailwind, sometimes classes can conflict or duplicate. This tool helps clean up your classes automatically, like having a smart assistant organize your closet.

Relevant when you receive props

Bad approach:

export const Button = ({ className, variant = 'primary', children }) => {
  const baseClasses = 'px-4 py-2 font-bold rounded'
  const variantClasses = variant === 'primary' 
    ? 'bg-blue-500 text-white' 
    : 'bg-gray-500 text-white'

  return (
    <button className={`${baseClasses} ${variantClasses} ${className}`}>
      {children}
    </button>
  )
}
Enter fullscreen mode Exit fullscreen mode

Good approach:

import { twMerge } from 'tailwind-merge'

export const Button = ({ className, variant = 'primary', children }) => {
  const baseClasses = 'px-4 py-2 font-bold rounded'
  const variantClasses = variant === 'primary' 
    ? 'bg-blue-500 text-white' 
    : 'bg-gray-500 text-white'

  return (
    <button className={twMerge(baseClasses, variantClasses, className)}>
      {children}
    </button>
  )
}
Enter fullscreen mode Exit fullscreen mode

10. Load data only when it's needed

Don't download all the movies on Netflix just in case you might want to watch them. Similarly, only load data when a user actually needs to see it, like when they click a button or scroll to a section.

  • Content data is loaded immediately when the page renders, even if the user hasn't clicked the "Show content" button.
  • This wastes data and makes your app load slower, even when users don't need this information.

Bad example:

import { useQuery } from '@tanstack/react-query'

export const Page = () => {
  const query = useQuery({
    queryKey: ['contents'],
    queryFn: fetchTableOfContents
  })

  return (
    <div>
      <button>Show content</button>
      {data && <div>{data.contents}</div>}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Good example #1:

import { useQuery } from '@tanstack/react-query'
import { useState } from 'react'

export const Page = () => {
  const [isOpen, setIsOpen] = useState(false)

  const query = useQuery({
    queryKey: ['contents'],
    queryFn: fetchTableOfContents,
    enabled: false
  })

  const handleShowContents = () => {
    setIsOpen(true)
    query.refetch()
  }

  return (
    <div>
      <button onClick={handleShowContents}>Show content</button>
      {isOpen && query.data && <div>{query.data.contents}</div>}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Good example #2:

import { useState } from 'react'
import dynamic from 'next/dynamic'

const TableOfContents = dynamic(
  () => import('../components/TableOfContents')
)

export const Page = () => {
  const [isOpen, setIsOpen] = useState(false)

  const handleShowContents = () => {
    setIsOpen(true)
  }

  return (
    <div>
      <button onClick={handleShowContents}>Show content</button>
      {isOpen && <TableOfContents />}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

  • These examples will help you follow best practices and improve the quality of your code.

  • 10 real-world mistakes
    
  • Clean code, clean architecture
    
  • For JS, TS, React, Node
    
  • Boost performance & clarity
    
  • Simple fixes, big impact
    

🔗 Watch a full video: https://youtu.be/Vd8lAIxa46Q

Top comments (0)