← All writing

React Hooks Best Practices

A comprehensive guide to using React Hooks effectively in your applications.

React Hooks revolutionized how we write React components. They allow us to use state and other React features in functional components, making our code more reusable and easier to understand. However, with great power comes great responsibility. Here are some best practices for using React Hooks effectively.

1. Only Call Hooks at the Top Level

Never call Hooks inside loops, conditions, or nested functions. Hooks must be called in the same order every time a component renders.

// ❌ Bad
function MyComponent({ condition }) {
  if (condition) {
    const [state, setState] = useState(0)
  }
  return <div>...</div>
}

// ✅ Good
function MyComponent({ condition }) {
  const [state, setState] = useState(0)
  if (condition) {
    // Use state here
  }
  return <div>...</div>
}

2. Use Custom Hooks for Reusable Logic

If you find yourself duplicating logic across components, extract it into a custom Hook.

// Custom Hook
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key)
      return item ? JSON.parse(item) : initialValue
    } catch (error) {
      return initialValue
    }
  })

  const setValue = (value) => {
    try {
      setStoredValue(value)
      window.localStorage.setItem(key, JSON.stringify(value))
    } catch (error) {
      console.error(error)
    }
  }

  return [storedValue, setValue]
}

// Usage
function MyComponent() {
  const [name, setName] = useLocalStorage("name", "")
  return <input value={name} onChange={(e) => setName(e.target.value)} />
}

3. Clean Up Side Effects

Always clean up side effects in useEffect to prevent memory leaks.

// ✅ Good
useEffect(() => {
  const subscription = subscribe()
  return () => {
    subscription.unsubscribe()
  }
}, [])

4. Include Dependencies in useEffect

Always include all dependencies in the dependency array. If you want to run an effect only once, use an empty array.

// ❌ Bad - missing dependency
useEffect(() => {
  fetchData(userId)
}, [])

// ✅ Good
useEffect(() => {
  fetchData(userId)
}, [userId])

5. Use useMemo and useCallback Wisely

Don’t overuse useMemo and useCallback. They’re optimization tools, not guarantees.

// Only use when necessary
const expensiveValue = useMemo(() => {
  return computeExpensiveValue(a, b)
}, [a, b])

const memoizedCallback = useCallback(() => {
  doSomething(a, b)
}, [a, b])

Conclusion

Following these best practices will help you write cleaner, more maintainable React code. Remember, Hooks are a tool - use them wisely and your components will be easier to understand and maintain.