Error Boundaries

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of crashing the entire component tree.

  • Creating an Error Boundary:

    class ErrorBoundary extends React.Component {
      constructor(props) {
        super(props);
        this.state = { hasError: false };
      }
    
      static getDerivedStateFromError() {
        // Update state so the next render will show the fallback UI
        return { hasError: true };
      }
    
      componentDidCatch(error, errorInfo) {
        // You can also log the error to an error reporting service
        console.error("Error caught by Error Boundary:", error, errorInfo);
      }
    
      render() {
        if (this.state.hasError) {
          // Fallback UI
          return <h1>Something went wrong.</h1>;
        }
    
        return this.props.children;
      }
    }
    
  • Usage in Application:

    function App() {
      return (
        <ErrorBoundary>
          <MyComponent />
        </ErrorBoundary>
      );
    }
    

Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them. They do not catch errors in event handlers, async code, server-side rendering, or errors thrown in the error boundary itself.

React Concurrent Mode

Concurrent Mode is an experimental feature in React that allows React to interrupt and pause rendering work to keep the app responsive. It enables new patterns for handling asynchronous rendering.

  • Key Concepts:

    • Suspense: Allows you to handle asynchronous loading of components. It enables fallback content while components are loading.

    • Transitions: Marks updates as non-urgent, allowing React to keep the app responsive by interrupting less important updates.

    • Suspense Example:

      const LazyComponent = React.lazy(() => import("./LazyComponent"));
      
      function App() {
        return (
          <React.Suspense fallback={<div>Loading...</div>}>
            <LazyComponent />
          </React.Suspense>
        );
      }
      

Server-Side Rendering (SSR)

SSR refers to the process of rendering your React components on the server rather than in the browser. This can improve the initial load time and SEO of your application.

Next.js, A popular framework for React that supports SSR out of the box.

import React from "react";
import ReactDOMServer from "react-dom/server";
import App from "./App";

const html = ReactDOMServer.renderToString(<App />);
// Send `html` as the response to the client

Static Site Generation (SSG)

SSG is a technique where pages are pre-rendered at build time into static HTML files, providing faster load times and better SEO.

Next.js Supports SSG with getStaticProps and getStaticPaths

export async function getStaticProps() {
  // Fetch data
  const data = await fetchData();
  return {
    props: { data },
  };
}

function Page({ data }) {
  return <div>{data}</div>;
}

React Hooks API

Functions that leverage React hooks to encapsulate reusable logic, enabling components to share behavior without changing their structure.

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

  React.useEffect(() => {
    try {
      window.localStorage.setItem(key, JSON.stringify(storedValue));
    } catch (error) {
      console.error(error);
    }
  }, [key, storedValue]);

  return [storedValue, setStoredValue];
}

What are refs in React?

Refs are used to get reference to a DOM node or an instance of a component. They help to access the DOM nodes or React elements created in the render method. You can also use refs when you want a component to “remember” some information, but you don’t want that information to trigger new renders, you can use a ref.

What is ref forwarding in React?

By default, each component’s DOM nodes are private. However, sometimes it’s useful to expose a DOM node to the parent—for example, to allow focusing it. To opt in, wrap your component definition into forwardRef():

import { forwardRef } from "react";

const MyInput = forwardRef(function MyInput(props, ref) {
  const { label, ...otherProps } = props;
  return (
    <label>
      {label}
      <input {...otherProps} />
    </label>
  );
});

You will receive a ref as the second argument after props. Pass it to the DOM node that you want to expose:

import { forwardRef } from "react";

const MyInput = forwardRef(function MyInput(props, ref) {
  const { label, ...otherProps } = props;
  return (
    <label>
      {label}
      <input {...otherProps} ref={ref} />
    </label>
  );
});

This lets the parent Form component access their <input> DOM node exposed by MyInput:

function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
  }

  return (
    <form>
      <MyInput label="Enter your name:" ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}

This Form component passes a ref to MyInput. The MyInput component forwards that ref to the <input> browser tag. As a result, the Form component can access that <input> DOM node and call focus() on it.

Portals

Portals provide a way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

import ReactDOM from "react-dom";

function Modal({ children }) {
  return ReactDOM.createPortal(children, document.getElementById("modal-root"));
}

Memoization Techniques

  • React.memo: A higher-order component that memoizes the output of a component to avoid unnecessary re-renders.

    const MyComponent = React.memo(function MyComponent(props) {
      // Component logic
    });
    
  • useMemo: A hook that memoizes the result of a calculation.

    const memoizedValue = React.useMemo(
      () => computeExpensiveValue(a, b),
      [a, b]
    );
    
  • useCallback: A hook that memoizes callback functions.

    const memoizedCallback = React.useCallback(() => {
      // Callback logic
    }, [dependencies]);
    

React DevTools

A browser extension that allows you to inspect and debug React component hierarchies, props, state, and performance.