Common pitfalls include: missing dependencies leading to stale closures, infinite loops from mutable values, unnecessary re-renders from object/array dependencies, and over-dependency on external values. Use ESLint rules and proper dependency management.
Use componentDidCatch and getDerivedStateFromError in class components for error boundaries. In functional components, use try-catch in event handlers and effects. Consider error boundary components for declarative error handling.
Both can initiate async operations but require different patterns. Class methods need mounted flags for safety, while hooks can use cleanup functions to cancel pending operations. Consider race conditions and component unmounting.
Use componentDidUpdate or useEffect with appropriate dependencies to react to prop changes. Consider memoization with useMemo for derived values and proper dependency array management in effects.
Manage focus in componentDidMount/Update or useEffect. Use refs for DOM element access. Consider accessibility implications and proper cleanup of focus-related effects.
Split effects by concern, manage dependencies independently, consider effect ordering, and implement proper cleanup for each effect. Use custom hooks to encapsulate related effect logic.
componentDidMount executes after the component mounts to the DOM. It's used for initial setup like API calls, subscriptions, or DOM manipulations. In hooks, this is achieved using useEffect with an empty dependency array: useEffect(() => {}, []).
getDerivedStateFromProps updates state based on prop changes. With hooks, use useEffect to observe prop changes and update state accordingly, but consider if derived state is really needed versus computing values during render.
In class components, use shouldComponentUpdate or extend PureComponent. In functional components, use React.memo for props comparison and useMemo/useCallback to prevent unnecessary re-renders of child components.
Constructor initializes state and binds methods in class components. In functional components, useState and useCallback replace these roles. Initial state can be set directly with useState, and function definitions handle method binding.
Set up subscriptions in componentDidMount or useEffect, clean up in componentWillUnmount or effect cleanup function. Handle subscription updates in componentDidUpdate or through effect dependencies. Ensure proper cleanup to prevent memory leaks.
Use console logs in lifecycle methods/effects, React DevTools for component mounting/updating visualization, and effect hooks lint rules. Implement proper error boundaries and logging for lifecycle events.
Trigger animations in componentDidMount/Update or useEffect. Handle cleanup in unmount phase. Consider using refs for DOM access and proper timing coordination with React's lifecycle.
Implement storage updates in effects or lifecycle methods, handle rehydration on mount, and clean up on unmount. Consider using localStorage/sessionStorage with proper serialization and cleanup.
The cleanup function runs before the component unmounts and before every re-render with changed dependencies. It's used to clean up subscriptions, event listeners, or timers to prevent memory leaks. Return a cleanup function from useEffect to implement it.
Use useEffect with appropriate dependency arrays: empty array for mount-only effects, specific dependencies for update effects, no array for every render, and cleanup function for unmount effects. Consider using multiple useEffect hooks to separate concerns.
Set up timers in componentDidMount or useEffect, clear them in componentWillUnmount or cleanup function. Use state or refs to track timer IDs. Ensure proper cleanup to prevent memory leaks and unexpected behavior.
Strict mode double-invokes certain lifecycle methods and hooks to help identify side effects. This includes constructor, render, and useEffect. Use it to catch lifecycle-related bugs and ensure proper cleanup implementation.
Use conditional logic inside effects or lifecycle methods, or split into multiple effects with different dependency arrays. Consider extracting complex conditions into separate functions for better maintainability.
Suspense can interrupt component mounting and trigger fallback rendering. Effects may be delayed or re-run. Consider the implications for data fetching, lazy loading, and error handling in lifecycle methods and effects.
Implement preloading in componentDidMount or useEffect with empty dependency array. Consider using Suspense for data fetching and lazy loading. Handle cleanup for abandoned preload requests.
The three main phases are: Mounting (component is created and inserted into DOM), Updating (component re-renders due to prop or state changes), and Unmounting (component is removed from DOM). Each phase has associated lifecycle methods or hooks.
useEffect combines the functionality of componentDidMount, componentDidUpdate, and componentWillUnmount. The effect runs after render, and its cleanup function (if returned) runs before unmount and before re-running the effect.
useEffect runs asynchronously after render completion, while useLayoutEffect runs synchronously before browser paint. useLayoutEffect is used for DOM measurements and mutations that need to be synchronized with rendering to prevent visual flicker.
componentWillUnmount handles cleanup before component removal. In hooks, return a cleanup function from useEffect to achieve the same. Use it to remove event listeners, cancel subscriptions, and clear timers to prevent memory leaks.
Use useState with initialization function for expensive computations, useEffect with empty dependency array for setup, and useMemo for computed initial values. Consider lazy initialization patterns to optimize performance.
Use componentDidMount or useLayoutEffect for DOM measurements to ensure the DOM is ready. Store measurements in state or refs. Consider resize observers and window event listeners with proper cleanup.
Avoid state updates in render phase. Use componentDidMount/Update or effects for async state updates. Consider batching updates and proper error handling. Be aware of setState's asynchronous nature.
Establish connections in componentDidMount or useEffect, handle reconnection logic in componentDidUpdate or with dependencies, and clean up in componentWillUnmount or effect cleanup. Consider connection state management.