React Development
๐Ÿ“’

React Development

Tags
Published
May 22, 2024

Component-Based Architecture

React is built around the concept of reusable components. Components are the building blocks of React applications, encapsulating both the structure (HTML) and behavior (JavaScript) of a part of the user interface[1][2].
Components can be as simple as a button or as complex as an entire page. They can be nested within each other, allowing developers to create complex UIs from smaller, manageable pieces. This modular approach makes it easier to maintain and scale applications.

Virtual DOM

One of React's most powerful features is its use of a Virtual DOM (Document Object Model). Instead of directly manipulating the browser's DOM, React creates a lightweight copy of it in memory[1][2].
When a component's state changes, React first updates the Virtual DOM. Then, it compares the updated Virtual DOM with a snapshot of the previous version (a process called "diffing"). Finally, it calculates the most efficient way to apply these changes to the real DOM. This process, known as reconciliation, significantly improves performance by minimizing direct manipulation of the DOM, which can be slow and resource-intensive.

Unidirectional Data Flow

React follows a unidirectional data flow. This means that data in a React application flows in a single direction: from parent components to child components[1].
This approach makes it easier to track where data comes from and how it changes over time, which helps in debugging and understanding the application's state. It also promotes a more predictable state management, as changes to the data can only happen in one way.

JSX

React uses JSX, a syntax extension for JavaScript that allows you to write HTML-like code within your JavaScript files[1]. For example:
const element = <h1>Hello, world!</h1>;
JSX makes it easier to describe what the UI should look like, and React takes care of rendering the actual DOM elements. While JSX is not required to use React, it significantly improves the development experience and code readability.

State and Props

React components can have two types of data: state and props.
State is data that can change over time. It's managed within a component and can be updated using the setState() method (in class components) or the useState hook (in functional components)[1].
Props (short for properties) are data passed from a parent component to a child component. Props are read-only, meaning a component should not modify the props it receives[1].
What happens if the prop passed in changed in a functional component?
If the prop changes in a functional component, React will re-render the component to reflect the updated prop values. This allows the component to react to the new data and update its output accordingly.
What happens if we call the functional component in two different places?
If we call the functional component in two different places, React will render two separate instances of the component, each with its own state and props. This allows each instance to function independently.

Lifecycle Methods and Hooks

React components go through a series of stages during their lifetime, from being created and mounted to the DOM, to being updated, and finally being unmounted and destroyed.
Class components use lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount to hook into these stages[1].
Functional components use Hooks, introduced in React 16.8, to achieve similar functionality. Hooks like useEffect allow you to perform side effects in function components, replacing several lifecycle methods[1].

React Component Lifecycle

notion image

Write the feature like useEffect in class declaration in React

In React, class components use lifecycle methods to achieve the same effects as the useEffect hook in functional components. useEffect serves multiple purposes based on how it's configured: it can run effects after every render, only once, or on certain updates depending on specified dependencies. Here's how you can replicate these behaviors using class component lifecycle methods:

1. Effect after Every Render

Equivalent to useEffect(() => { ... }) without dependencies.
  • Class Component Method: componentDidMount and componentDidUpdate
class MyComponent extends React.Component { componentDidMount() { // Code to run on component mount } componentDidUpdate() { // Code to run on every update } render() { return <div>...</div>; } }

2. Effect Only Once (On Mount)

Equivalent to useEffect(() => { ... }, []).
  • Class Component Method: componentDidMount
jsxCopy code class MyComponent extends React.Component { componentDidMount() { // Code to run only once after the component mounts } render() { return <div>...</div>; } }

3. Effect with Cleanup

Equivalent to using a return function in useEffect for cleanup purposes, such as unsubscribing from subscriptions or clearing timers.
  • Class Component Method: componentDidMount for setting up and componentWillUnmount for cleanup
jsxCopy code class MyComponent extends React.Component { componentDidMount() { // Setup code, e.g., starting a timer this.timerID = setInterval(() => this.tick(), 1000); } componentWillUnmount() { // Cleanup code, e.g., clearing a timer clearInterval(this.timerID); } tick() { // Do something every second } render() { return <div>...</div>; } }

4. Effect On Specific Updates Only

Equivalent to useEffect(() => { ... }, [deps]) where deps are dependencies that trigger the effect when changed.
  • Class Component Method: componentDidUpdate
    • You must manually compare props or state to see if they have changed.
jsxCopy code class MyComponent extends React.Component { componentDidUpdate(prevProps, prevState) { // Only run code when specific prop or state has changed if (prevProps.userID !== this.props.userID) { this.fetchUserData(this.props.userID); } } fetchUserData(userID) { // Fetch user data } render() { return <div>...</div>; } }

Example: Converting a useEffect with Dependencies

If you have a functional component using useEffect like so:
jsxCopy code useEffect(() => { const subscription = props.source.subscribe(); return () => { subscription.unsubscribe(); }; }, [props.source]);
The equivalent class component using lifecycle methods would be:
jsxCopy code class MyComponent extends React.Component { componentDidMount() { this.subscribe(); } componentDidUpdate(prevProps) { if (this.props.source !== prevProps.source) { this.unsubscribe(); this.subscribe(); } } componentWillUnmount() { this.unsubscribe(); } subscribe() { this.subscription = this.props.source.subscribe(); } unsubscribe() { if (this.subscription) { this.subscription.unsubscribe(); } } render() { return <div>...</div>; } }
In this way, you can replicate any useEffect behavior using class component lifecycle methods, although the syntax and specifics of implementation differ slightly.

Conclusion

React's component-based architecture, Virtual DOM, unidirectional data flow, and state management make it a powerful tool for building dynamic user interfaces. By breaking UIs into reusable components and efficiently updating the DOM, React allows developers to create fast, scalable, and maintainable web applications.
Understanding these core concepts is crucial for effectively using React and leveraging its full potential in your projects. As you delve deeper into React development, you'll discover more advanced features and patterns that build upon these fundamental principles.

A minimal React Framework From Scratch

Citations