React

What is React?

React is a JavaScript library for building user interfaces, primarily single-page applications (SPAs). It allows developers to create reusable UI components, which manage their own state and then update dynamically as the data changes. React follows a component-based architecture, making it easy to create complex interfaces by combining smaller, modular components. One of its core features is the virtual DOM, which optimizes updates to the actual DOM for better performance.


React DOM

React DOM is the library that connects React to the actual Document Object Model (DOM) in web browsers. While React itself is concerned with how components are built and managed, React DOM takes care of rendering those components in the browser. It provides methods to manipulate the DOM, such as render(), which mounts a React component to a DOM node.


Virtualization in React

Virtualization in React typically refers to the technique used to improve performance when rendering large lists or grids of elements. Instead of rendering all the items in a list at once, virtualization only renders the visible portion of the list (or slightly more), and dynamically loads more elements as the user scrolls. This reduces the amount of work the browser has to do, which improves both rendering speed and memory usage.


JSX

JSX is a syntax extension for JavaScript that allows you to write HTML-like code directly within your JavaScript files. Instead of using the traditional React.createElement() to create elements, JSX lets you write markup that looks almost identical to HTML, making your components easier to understand and maintain.


TSX

TSX (TypeScript XML) is the TypeScript version of JSX. It allows you to write HTML-like syntax within TypeScript code, just as JSX does within JavaScript. However, TSX also incorporates TypeScript's type-checking and other features, which brings the benefits of type safety and better tooling to React development.


Functional Components & Class based Components

In React, components can be created in two ways: as function components or class-based components. Both can be used to build UIs, but they differ in syntax, capabilities (especially before React Hooks were introduced), and best practices. Let's break down the key differences and advantages of each:

  • Function Components:
    • Definition: Simple JavaScript functions that return JSX.
    • State: Managed with hooks like useState and side effects with useEffect.
    • No this keyword: State and props are accessed directly without needing this.
    • Performance: Typically lighter and easier to read.
    • Preferred: In modern React, function components are favored due to their simplicity and hooks support.
  • Class Components:
    • Definition: JavaScript ES6 classes that extend React.Component.
    • State: Managed via this.state and updated with this.setState().
    • Lifecycle Methods: Uses built-in methods like componentDidMount and componentDidUpdate.
    • Requires this: Methods and state need careful handling of the this keyword.
    • Legacy: Used in older codebases, but still fully supported.
  • Key Differences:
    • Simplicity: Function components are cleaner and more concise.
    • State and Lifecycle: Handled via hooks (useState, useEffect) in function components vs. state and lifecycle methods in class components.
    • Best Practice: Function components are now the preferred approach in modern React development.

React Life Cycle

                Simple flow of the lifecycle:
                Mounting
                    ↓
                    constructor() 
                    ↓
                    static getDerivedStateFromProps()
                    ↓
                    render()
                    ↓
                    componentDidMount()

                Updating
                    ↓
                    static getDerivedStateFromProps()
                    ↓
                    shouldComponentUpdate()
                    ↓
                    render()
                    ↓
                    getSnapshotBeforeUpdate()
                    ↓
                    componentDidUpdate()

                Unmounting
                    ↓
                    componentWillUnmount()
              

Using Lifecycle Methods in Function Components:

  • With the introduction of Hooks, many lifecycle methods can be replicated using the useEffect hook in function components.
  • componentDidMount: Can be replicated with useEffect that runs only on mount.
  • componentDidUpdate: Can be handled by specifying dependencies in the useEffect array.
  • componentWillUnmount: Can be handled by returning a cleanup function from useEffect.

                Using Lifecycle Methods in Function Components:
                import React, { useState, useEffect } from 'react';

                function ExampleComponent() {
                  const [count, setCount] = useState(0);
                
                  useEffect(() => {
                    console.log('Component updated');
                    // This return function acts like componentWillUnmount
                    return () => {
                      console.log('Cleanup before unmounting');
                    };
                  }, [count]); // Runs whenever 'count' changes

                  
                  // This effect runs after the first render (like componentDidMount)
                  useEffect(() => {
                    console.log('Component mounted');
                
                    // This return function acts like componentWillUnmount
                    return () => {
                      console.log('Cleanup before unmounting');
                    };
                  }, []);

                
                  return (
                    < div>
                      < p>You clicked {count} times
                      < button onClick={() => setCount(count + 1)}>Click me < /button>
                    < /div>
                  );
                }
            

Summary:

  • Understanding the React lifecycle helps you manage component behavior effectively.
  • Class components have specific lifecycle methods that can be overridden, while function components use hooks like useEffect to manage similar behaviors.
  • Proper use of lifecycle methods ensures efficient performance and resource management in React applications.

React Hooks

React Hooks are special functions that allow you to use state and other React features in functional components. They were introduced in React 16.8 to enable functional components to manage state and lifecycle events without converting them into class components. Here’s an overview of the most commonly used hooks and their purposes:

  • Key React Hooks:
    • useState: Allows you to add state to functional components. Returns an array with the current state value and a function to update it.
    • useEffect: Enables you to perform side effects in your components, such as data fetching or manual DOM manipulations. Takes a function with the side effect logic and an optional dependency array.
    • useContext: Allows access to the context API, making it easier to share values like themes or user information across components without prop drilling.
    • useReducer: A more advanced alternative to useState, used for managing complex state logic in a predictable way.
    • useMemo and useCallback: Optimize performance by memoizing values and functions. useMemo memoizes the result of a computation, while useCallback memoizes a function definition.
  • Custom Hooks: You can create your own hooks to encapsulate reusable logic, which is a JavaScript function that calls one or more hooks.
  • Benefits of Using Hooks:
    • Simplified Component Logic: Hooks allow you to write components that are easier to understand and manage.
    • Reusability: Custom hooks enable you to encapsulate and share stateful logic across components.
    • Cleaner Code: They help reduce boilerplate code associated with class components and provide a more functional approach.
  • Conclusion: React Hooks enhance the capabilities of functional components, enabling efficient management of state and side effects, leading to organized and maintainable code in React applications.

React Stores

In React, stores refer to a centralized way of managing and maintaining the application state. They are part of a state management approach that helps to simplify the process of sharing state across different components, making it easier to manage complex applications. There are several ways to implement stores in React, each with its own set of tools and patterns. Here are some of the most commonly used methods:

  • 1. Context API
    • Overview: A built-in feature of React that allows you to create a global state accessible to any component without passing props manually.
    • Usage:
      • Create a context using React.createContext().
      • Use a Provider to wrap your component tree and supply the state.
      • Use the useContext hook in any component to access the context value.
  • 2. Redux
    • Overview: A popular state management library that provides a structured way to manage state through a single global store.
    • Key Concepts:
      • Store: A single source of truth for the application's state.
      • Actions: Plain JavaScript objects that describe what happened in the application.
      • Reducers: Pure functions that take the current state and an action and return a new state.
      • Dispatch: A function used to send actions to the store.
    • Usage:
      • Set up a Redux store using createStore().
      • Use the Provider from react-redux to make the store available to components.
      • Connect components to the store using the connect function or the useSelector and useDispatch hooks.
  • 3. MobX
    • Overview: A state management library that focuses on making state management simple and scalable through observable states.
    • Key Concepts:
      • Observable: Any state can be made observable, automatically tracking its usage and updates.
      • Actions: Functions that modify the state.
      • Computed Values: Values that derive from observable state, automatically updating when the state changes.
    • Usage:
      • Use makeObservable or makeAutoObservable to define observable properties and actions in your stores.
      • Use the Observer component or the useObserver hook to reactively render components based on observable state.
  • 4. Zustand
    • Overview: A small, fast, and scalable state management solution that leverages hooks.
    • Key Features:
      • Simple API that allows you to create a store using hooks.
      • Lightweight with no dependencies.
    • Usage:
      • Create a store using create().
      • Use the store in components by calling the store function directly.
  • 5. Recoil
    • Overview: A state management library that provides a way to manage shared state with a flexible and scalable approach.
    • Key Concepts:
      • Atoms: Units of state that can be read from and written to from any component.
      • Selectors: Functions that derive state from atoms or other selectors.
    • Usage:
      • Define atoms using atom().
      • Use useRecoilState() to read and write atom values in components.
  • Benefits of Using Stores:
    • Centralized State Management: Simplifies data flow and management across components.
    • Predictability: State changes can be more predictable and easier to debug with libraries like Redux or MobX.
    • Separation of Concerns: Helps keep UI logic and business logic separate, promoting cleaner code.
  • Choosing a Store Solution:
    • Simple Applications: Context API may suffice for lightweight state management.
    • Medium to Large Applications: Redux or MobX can provide more structure and features.
    • Highly Dynamic Applications: Libraries like Recoil or Zustand may offer the flexibility and performance needed.
  • Conclusion: React stores play a crucial role in managing state across applications, providing various solutions to meet different needs, leading to better organization and maintainability of your React code.

React Profiler

  • Overview:
    • Measures the rendering behavior of components.
    • Identifies performance bottlenecks and optimizes applications.
  • Key Features:
    • Render Timing: Captures time taken for each component to render.
    • Commit Phase Tracking: Tracks how long the commit phase takes.
    • Interaction Tracking: Visualizes how interactions affect rendering.
    • Flamegraph Visualization: Displays rendering data in a flamegraph format.
  • Usage:
    • Enable Profiler in React DevTools.
    • Record a profiling session by interacting with the app.
    • Analyze results to identify performance issues.
  • Common Performance Issues:
    • Unnecessary Re-renders: Use React.memo to avoid.
    • Heavy Components: Optimize with code splitting or lazy loading.
    • Excessive State Updates: Batch updates to minimize renders.
  • Benefits:
    • Provides performance insights for optimization.
    • Helps identify components that can be improved.
    • Enables real-time analysis during development.
  • Conclusion: The React Profiler is essential for optimizing React applications, leading to better performance and user experience.

React Concurrent Mode vs Suspense

  • React Concurrent Mode
    • Overview: A set of features that allow components to render asynchronously for a more responsive UI.
    • Key Features:
      • Concurrent Rendering: Renders multiple tasks simultaneously.
      • Transition APIs: Marks updates as non-urgent for better prioritization.
      • Scheduling: Interrupts rendering for higher-priority updates.
    • Use Cases: Best for complex UIs needing responsiveness during data fetching and user interactions.
  • Suspense
    • Overview: Handles loading states for asynchronous data in a graceful way.
    • Key Features:
      • Data Fetching: Suspends rendering until data is loaded.
      • Fallback UI: Displays a loading spinner or message while waiting for data.
      • Integration: Works seamlessly with Concurrent Mode.
    • Use Cases: Ideal for components that rely on asynchronous data fetching.
  • Key Differences:
    • Purpose: Concurrent Mode optimizes rendering performance; Suspense manages loading states.
    • Functionality: Concurrent Mode affects rendering behavior; Suspense handles loading states.
    • Usage: Concurrent Mode impacts the entire application; Suspense is used in specific components for data fetching.
  • Conclusion: Both features improve user experience by making applications more responsive and easier to manage during asynchronous operations.

REACT HOCs and Render Props

  • Higher-Order Components (HOCs)
    • Definition: A Higher-Order Component is a function that takes a component and returns a new component.
    • Purpose: Used for code reuse and abstraction to share functionality across components.
    • Usage: Common for adding logging, authentication checks, or data fetching.
    • Example:
          const withEnhancements = (WrappedComponent) => {
              return class extends React.Component {
              render() {
                  // Add extra props or behavior
                  return < WrappedComponent {...this.props} extraProp="value" />;
              }
              };
          };
              
    • Benefits: Promotes code reuse and separation of concerns, enhancing functionality without altering original components.
  • Render Props
    • Definition: A Render Prop is a technique for sharing code using a prop whose value is a function.
    • Purpose: To provide flexibility in how components render content by passing state or behavior.
    • Usage: Commonly used for managing state or handling subscriptions.
    • Example:
              class DataProvider extends React.Component {
                  state = { data: null };
      
                  componentDidMount() {
                  // Fetch data and update state
                  }
      
                  render() {
                  return this.props.render(this.state.data);
                  }
              }
      
              // Usage
              < DataProvider render={data => < MyComponent data={data} />} />
              
    • Benefits: Offers greater rendering flexibility and avoids prop name collisions.
  • Key Differences:
    • Structure: HOCs wrap components; Render Props use a function as a prop.
    • Use Cases: HOCs are for cross-cutting concerns; Render Props are for state sharing.
    • Complexity: HOCs can lead to "wrapper hell"; Render Props keep the hierarchy simpler.
  • Conclusion: Both patterns are powerful for sharing functionality and state, promoting reusable and maintainable code in React applications.

Resource Links Used


OpenAI - ChatGPT