reactnotes

Pros and Cons

  1. React is a library; it initially only included components.
  2. We need to install additional libraries for features like routing.
  3. It is the most popular JavaScript library, so there are thousands of libraries, community support, etc.

Building Blocks of React

  1. Components: Reusable blocks of code that return HTML.
  2. JSX: JavaScript and XML syntax that allows writing HTML in React.
  3. Props and State: Props are like function parameters, and state acts as variables.
  4. Context: Allows data to be passed through components in a hierarchy as props.
  5. Virtual DOM: A lightweight copy of the actual DOM, which makes DOM manipulation more efficient. React manipulates the virtual DOM first, then updates the real DOM.

JSX

  1. JSX: Combines JavaScript and XML syntax.
  2. Allows HTML to be written within JavaScript code.
  3. Syntactic sugar over React.createElement.
  4. Under the hood, React creates elements for us based on the HTML we write.
  5. Allows us to write markup in JavaScript.
  6. Provides direct access to all properties.

What is the difference between an element and a component in React?

An element is a plain JavaScript object that represents a DOM node or component. Elements are pure and never mutated, and are cheap to create.

A component is a function or class. Components can have state and take props as input and return an element tree as output (although they can represent generic containers or wrappers and don’t necessarily have to emit DOM). Components can initiate side effects in lifecycle methods (e.g., AJAX requests, DOM mutations, interfacing with 3rd party libraries) and may be expensive to create.

const Component = () => "Hello";
const componentElement = <Component />;
const domNodeElement = <div />;
  • Elements are immutable, plain objects that describe the DOM nodes or components you want to render.
  • Components can be either classes or functions, that take props as an input and return an element tree as the output.

Functional Components

  1. React functional components: JavaScript functions; they are not aware of the other components in the program.

  2. App is a functional component, which returns some markup.

  3. A functional component doesn’t have a state inside.

  4. Replacing with classes:

    Example
    import React from "react";
     
    class Button extends React.Component {
      // classes can have states! don't need hooks
      state = {
        counter: 0,
      };
     
      // lifecycle hooks
      componentDidMount() {
        console.log("created Button");
      }
      render() {
        return (
          <button
            onClick={() => this.setState({ counter: this.state.counter + 1 })}
          >
            {this.props.text} {this.state.counter}
          </button>
        );
      }
    }
     
    class App extends React.Component {
      render() {
        return (
          <div className="app">
            <Button text="Hello React" />
          </div>
        );
      }
    }

What is a stateless component?

A stateless component is a component whose behavior does not depend on its state. Stateless components can be either functional or class components. Stateless functional components are easier to maintain and test since they are guaranteed to produce the same output given the same props. Stateless functional components should be preferred when lifecycle hooks don’t need to be used.

  • Stateless components are independent of their state.
  • Stateless components can be either class or functional components.
  • Stateless functional components avoid the this keyword altogether.

What is a stateful component in React?

A stateful component is a component whose behavior depends on its state. This means that two separate instances of the component if given the same props will not necessarily render the same output, unlike pure function components.

// Stateful class component
class App extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
  render() {
    // ...
  }
}
 
// Stateful function component
function App() {
  const [count, setCount] = useState(0);
  return; // ...
}
  • Stateful components have internal state that they depend on.
  • Stateful components are class components or function components that use stateful Hooks.
  • Stateful components have their state initialized in the constructor or with useState().

Virtual DOM

  1. The virtual DOM is a lightweight JavaScript representation of the DOM.
  2. In JavaScript, a DOM tree is created to render content in the browser, but creating nodes in this tree can be slow and code-intensive.
  3. In React, the virtual DOM is a large object that helps React efficiently compare states and make changes.
  4. Allows us to write declarative code without directly manipulating the DOM.
  5. Difference between Virtual DOM and Shadow DOM: The shadow DOM is not related to React.

Data Flow in React

  1. Data flow is unidirectional, flowing downward from parent to child.
  2. Information is passed through props.
  3. Redux provides global state management, helping to avoid prop drilling.

What does lifting state up in React mean?

When several components need to share the same data, then it is recommended to lift the shared state up to their closest common ancestor. For example, if two child components share the same data, it is recommended to move the shared state to parent instead of maintaining the local state in both child components.

Dumb/Presentational Components vs Smart/Container Components

  1. A dumb/presentation component doesn’t have any logic or state inside.
  2. A smart/container component has at least a state.

The React Lifecycle

  1. Mounting: Component is created and inserted into the DOM.
  2. Updating: Component updates when props or state change.
  3. Unmounting: Component is removed from the DOM.

What are the different phases of the component lifecycle in React?

There are four different phases of component’s lifecycle:

Initialization: In this phase, the component prepares setting up the initial state and default props.

Mounting: The react component is ready to mount to the DOM. This phase covers the getDerivedStateFromProps and componentDidMount lifecycle methods.

Updating: In this phase, the component gets updated in two ways, sending the new props and updating the state. This phase covers the getDerivedStateFromProps, shouldComponentUpdate, getSnapshotBeforeUpdate and componentDidUpdate lifecycle methods.

Unmounting: In this last phase, the component is not needed and gets unmounted from the browser DOM. This phase includes the componentWillUnmount lifecycle method.

Error Handling: In this phase, the component is called whenever there’s an error during rendering, in a lifecycle method, or in the constructor for any child component. This phase includes the componentDidCatch lifecycle method.

Lifecycle Methods of Components

  1. Initialization: The component is constructed with given props and default state.
  2. Mounting: The component renders the JSX returned by its render method.
  3. Updating: The component’s state is updated, and the application is re-rendered.
  4. Unmounting: The component is removed from the page.

What are the lifecycle methods in React?

getDerivedStateFromProps: Executed before rendering on the initial mount and all component updates. Used to update the state based on changes in props over time. Has rare use cases, like tracking component animations during the lifecycle. There are only few cases where this makes sense to use over other lifecycle methods. It expects to return an object that will be the the new state, or null to update nothing. This method does not have access to the component instance either.

componentDidMount: Executed after first rendering and here all AJAX requests, DOM or state updates, and set up eventListeners should occur.

shouldComponentUpdate: Determines if the component will be updated or not. By default, it returns true. If you are sure that the component doesn’t need to render after state or props are updated, you can return a false value. It is a great place to improve performance as it allows you to prevent a rerender if component receives new prop.

getSnapshotBeforeUpdate: Invoked right after a component render happens because of an update, before componentDidUpdate. Any value returned from this method will be passed to componentDidUpdate.

componentDidUpdate: Mostly it is used to update the DOM in response to prop or state changes.

componentWillUnmount: It will be used to cancel any outgoing network requests, or remove all event listeners associated with the component.

componentDidCatch: Used in error boundaries, which are components that implement this method. It allows the component to catch JavaScript errors anywhere in the child component tree (below this component), log errors, and display a UI with error information.

Performing a Function Before Component Unmounts

  1. Use the useEffect hook with a cleanup function.
  2. The cleanup function runs before the component unmounts.

Hooks

  1. React Hooks: Enable developers to use state and other features without writing classes. Hooks provide a direct API to React concepts such as props, state, context, refs, and lifecycle methods.
  2. Custom Hooks: Normal JavaScript functions that start with “use” and may call other hooks.

The 5 React Hooks and Their Use Cases

  1. useState: Manages state in functional components.
  2. useEffect: Performs side effects like data fetching or subscriptions.
  3. useContext: Accesses values from the React context.
  4. useRef: Creates a mutable reference that persists across re-renders.
  5. useReducer: Manages complex state logic using a reducer function.

Implementing React Lifecycle Methods in Functional Components

  1. Use the useEffect hook to replicate lifecycle methods.
  2. Specify an empty dependency array to run an effect only once (like componentDidMount).
  3. Return a cleanup function to run code before the component unmounts (like componentWillUnmount).

How to Delay an API Call Until a Component is Mounted

  1. Traditional approach: Use componentDidMount.
  2. In functional components with hooks, use useEffect with an empty dependency array.

Redux

  1. React-Redux: A state management tool that allows states to be shared between components regardless of their position in the component tree.
    1. Provides centralized state management.
    2. Optimizes performance by preventing unnecessary re-renders.
    3. Simplifies debugging.
  2. Core Components of React-Redux:
    1. Redux Store: An object that holds the application state.
    2. Action Creators: Functions that return actions (objects).
    3. Actions: Simple objects with two properties, type and payload.
    4. Reducers: Pure functions that update the application state in response to actions.
  3. Context API:
    1. Used to pass global variables anywhere in the code.
    2. Lightweight and easy to use; create a context by calling createContext().
    3. Serves as an alternative to Redux.
    4. Has two main properties: provider and consumer.
  4. Context API Properties:
    1. Provider: Used to provide context to the entire application.
    2. Consumers: Used to consume the context.

Redux Over Context API

  1. Performance Issues: Context API can lead to unnecessary re-renders, especially when dealing with deeply nested components. Redux, with its optimized updates and middleware, handles large-scale state changes more efficiently.
  2. Limited Middleware Support: Redux offers a rich ecosystem of middleware like Redux Thunk and Redux Saga, which are crucial for handling side effects, async actions, and more complex state logic. Context API lacks such built-in support, making it less flexible for handling advanced use cases.
  3. Scalability Concerns: Context API is great for small to medium-sized applications, but as your app grows, managing state with Context alone can become cumbersome. Redux, with its well-defined structure, is better suited for scaling applications.
  4. Developer Tools: Redux has robust dev tools that allow you to easily track actions, state changes, and even time travel debugging. Context API doesn’t offer the same level of tooling, making it harder to debug and inspect state changes.
  5. Single Source of Truth: Redux encourages a single, centralized store for your application state, which makes it easier to maintain and predict state changes. Context API, on the other hand, can lead to multiple scattered contexts, increasing the risk of inconsistent state management.

Difference Between React and Next.js

  1. React is a JavaScript library for building user interfaces.
  2. Next.js is a framework built on top of React.
  3. Next.js adds server-side rendering, routing, and other features to React.

Key Features of Next.js

  1. Server-side rendering and static site generation.
  2. Automatic code splitting for faster page loads.
  3. Built-in routing and API routes.
  4. Easy deployment to Vercel or other hosting platforms.

Identifying Client-Side vs Server-Side Rendered Websites

  1. View the page source; if it contains the full HTML content, it’s server-side rendered.
  2. Disable JavaScript; if the page still loads and displays content, it’s server-side rendered.
  3. Check the network tab; if the initial HTML payload is small and additional requests are made, it’s client-side rendered.

How Next.js Works Behind the Scenes

  1. Next.js pre-renders pages on the server, generating HTML for each page
  2. For static pages, Next.js generates the HTML at build time
  3. For server-rendered pages, Next.js generates the HTML on each request
  4. Next.js automatically splits the JavaScript code for optimal performance

Reconciliation in React

  1. Reconciliation is the process React uses to update the DOM based on state changes.
  2. React builds a virtual DOM and compares it to the previous virtual DOM.
  3. React calculates the minimal set of changes needed and applies them to the real DOM.

Benefits of Reconciliation in React

  1. Efficient updates to the DOM.
  2. Minimizes the number of DOM manipulations.
  3. Improves performance by reducing unnecessary re-renders.

Memoization in React

  1. Memoization is an optimization technique that caches the results of expensive function calls.
  2. In React, memoization is used to avoid unnecessary re-renders of components.
  3. React provides memo, useMemo, and useCallback for memoization.

Optimization

  1. Ways to Optimize React Code:
    1. Bind functions in constructors.
    2. Avoid inline attributes.
    3. Use React fragments to eliminate extra tags.
    4. Implement lazy loading.

Performing Form Validation in React

  1. Use controlled components to manage form state.
  2. Validate form fields on change and/or submit events.
  3. Display validation errors to the user.
  4. Prevent form submission if validation fails.

How do you write comments inside a JSX tree in React?

Comments must be wrapped inside curly braces {} and use the /* */ syntax.

const tree = (
  <div>
    {/* Comment */}
    <p>Text</p>
  </div>
);

Why does React use className instead of class like in HTML?

React’s philosophy in the beginning was to align with the browser DOM API rather than HTML, since that more closely represents how elements are created. Setting a class on an element meant using the className API:

const element = document.createElement("div");
element.className = "hello";

Additionally, before ES5, reserved words could not be used in objects:

const element = {
  attributes: {
    class: "hello",
  },
};

In IE8, this will throw an error.

In modern environments, destructuring will throw an error if trying to assign to a variable:

const { class } = this.props // Error
const { className } = this.props // All good
const { class: className } = this.props // All good, but cumbersome!

However, class can be used as a prop without problems, as seen in other libraries like Preact. React currently allows you to use class, but will throw a warning and convert it to className under the hood. There is currently an open thread (as of January 2019) discussing changing className to class to reduce confusion.

What is the purpose of callback function as an argument of setState?

The callback function is invoked when setState has finished and the component gets rendered. Since setState is asynchronous, the callback function is used for any post action.

setState({ name: "sudheer" }, () => {
  console.log("The name has updated and component re-rendered");
});
  • The callback function is invoked after setState finishes and is used for any post action.
  • It is recommended to use lifecycle method rather this callback function.

How do you pass an argument to an event handler or callback?

You can use an arrow function to wrap around an event handler and pass arguments, which is equivalent to calling bind:

<button onClick={() => this.handleClick(id)} />
<button onClick={this.handleClick.bind(this, id)} />

What are inline conditional expressions?

Since a JSX element tree is one large expression, you cannot embed statements inside. Conditional expressions act as a replacement for statements to use inside the tree.

For example, this won’t work:

function App({ messages, isVisible }) {
  return (
    <div>
      if (messages.length > 0){" "}
      {<h2>You have {messages.length} unread messages.</h2>} else{" "}
      {<h2>You have no unread messages.</h2>}
      if (isVisible) {<p>I am visible.</p>}
    </div>
  );
}

Logical AND && and the ternary ? : operator replace the if/else statements.

function App({ messages, isVisible }) {
  return (
    <div>
      {messages.length > 0 ? (
        <h2>You have {messages.length} unread messages.</h2>
      ) : (
        <h2>You have no unread messages.</h2>
      )}
      {isVisible && <p>I am visible.</p>}
    </div>
  );
}

What is a key? What are the benefits of using it in lists?

Keys are a special string attribute that helps React identify which items have been changed, added, or removed in a list. They are essential for ensuring stable identity across re-renders and should be unique within their list context. Using keys improves performance and helps React minimize updates.

const todoItems = todos.map((todo) => <li key={todo.id}>{todo.text}</li>);
  • Avoid using indexes as keys if the order of items may change, as this can cause issues with component state and reordering.
  • If list items are extracted as a separate component, apply keys on the component level rather than the <li> tag itself.

Which is the preferred option between callback refs and findDOMNode()?

Callback refs are preferred over the findDOMNode() API because findDOMNode() can interfere with certain React optimizations and future improvements.

// Legacy approach using findDOMNode()
class MyComponent extends Component {
  componentDidMount() {
    findDOMNode(this).scrollIntoView();
  }
 
  render() {
    return <div />;
  }
}
 
// Recommended approach using callback refs
class MyComponent extends Component {
  componentDidMount() {
    this.node.scrollIntoView();
  }
 
  render() {
    return <div ref={(node) => (this.node = node)} />;
  }
}
  • Callback refs provide a more flexible and recommended approach.

What are fragments?

Fragments allow React components to return multiple elements without an extra wrapper in the DOM. This reduces DOM nodes, improves performance, and simplifies CSS mechanisms such as tables, Flexbox, and Grid.

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}
 
// Short syntax supported by Babel 7
render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}
  • Fragments enable grouping of elements returned from a component without an additional DOM wrapper.

How do you ensure methods have the correct this context in React component classes?

In JavaScript classes, methods are not bound by default, meaning their this context can change depending on how they are called. To fix this, you can use Function.prototype.bind() in the constructor to ensure this refers to the component instance.

constructor(props) {
  super(props);
  this.handleClick = this.handleClick.bind(this);
}
 
handleClick() {
  // Perform some logic
}
  • Alternatively, you can use the public class fields syntax to define methods with lexical this, preserving the component instance context:
handleClick = () => {
  console.log('this is:', this);
}
 
render() {
  return (
    <button onClick={this.handleClick}>
      Click me
    </button>
  );
}
  • Using inline arrow functions is another option but may lead to extra re-renders. For better performance, bind in the constructor or public class fields syntax is preferred.

What are error boundaries in React?

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

Class components become error boundaries if they define the lifecycle methods static getDerivedStateFromError() and/or componentDidCatch().

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
 
  componentDidCatch(error, info) {
    logErrorToMyService(error, info);
  }
 
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
 
  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}
  • Error boundaries catch errors in components below them but not within themselves.

What are higher-order components?

A higher-order component (HOC) is a function that takes a component as an argument and returns a new component. It’s a pattern that leverages React’s compositional nature to enhance or modify components without altering their structure.

const EnhancedComponent = higherOrderComponent(WrappedComponent);
  • HOCs can be used for state abstraction, props manipulation, render hijacking, and other advanced functionality.

How to apply prop validation in React?

When the application is running in development mode, React will automatically check for all props that we set on components to make sure they are the correct data type. For incorrect data types, it will generate warning messages in the console for development mode. They are stripped in production mode due to their performance impact. Required props are defined with isRequired.

For example, we define propTypes for component as below:

import PropTypes from "prop-types"
 
class User extends React.Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number.isRequired
  }
 
  render() {
    return (
      <h1>Welcome, {this.props.name}</h1>
      <h2>Age, {this.props.age}
    )
  }
}
  • We can define custom propTypes
  • Using propTypes is not mandatory. However, it is a good practice and can reduce bugs.

What is context?

Context provides a way to pass data through the component tree without having to pass props down manually at every level. For example, authenticated user, locale preference, UI theme need to be accessed in the application by many components.

const { Provider, Consumer } = React.createContext(defaultValue);
  • Context provides a way to pass data through a tree of React components, without having to manually pass props.
  • Context is designed to share data that is considered global for a tree of React components.

What are refs in React? When should they be used?

Refs provide a way to access DOM nodes or React elements created in the render method. Refs should be used sparringly, but there are some good use cases for refs, such as:

  • Managing focus, text selection, or media playback.
  • Triggering imperative animations.
  • Integrating with third-party DOM libraries.

Refs are created using React.createRef() method and attached to React elements via the ref attribute. In order to use refs throughout the component, assign the ref to the instance property within the constructor:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
 
  render() {
    return <div ref={this.myRef} />;
  }
}

Refs can also be used in functional components with the help of closures.

  • Refs are used to return a reference to an element.
  • Refs shouldn’t be overused.
  • You can create a ref using React.createRef() and attach to elements via the ref attribute.

What is the children prop?

children is part of the props object passed to components that allows components to be passed as data to other components, providing the ability to compose components cleanly. There are a number of methods available in the React API to work with this prop, such as React.Children.map, React.Children.forEach, React.Children.count, React.Children.only and React.Children.toArray. A simple usage example of the children prop is as follows:

function GenericBox({ children }) {
  return <div className="container">{children}</div>;
}
 
function App() {
  return (
    <GenericBox>
      <span>Hello</span> <span>World</span>
    </GenericBox>
  );
}
  • Children is a prop that allows components to be passed as data to other components.
  • The React API provides methods to work with this prop.

What are portals in React?

Portal are the recommended way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

ReactDOM.createPortal(child, container);

The first argument (child) is any renderable React child, such as an element, string, or fragment. The second argument (container) is a DOM element.

What are the lifecycle methods in React?

getDerivedStateFromProps: Executed before rendering on the initial mount and all component updates. Used to update the state based on changes in props over time. Has rare use cases, like tracking component animations during the lifecycle. There are only few cases where this makes sense to use over other lifecycle methods. It expects to return an object that will be the the new state, or null to update nothing. This method does not have access to the component instance either.

componentDidMount: Executed after first rendering and here all AJAX requests, DOM or state updates, and set up eventListeners should occur.

shouldComponentUpdate: Determines if the component will be updated or not. By default, it returns true. If you are sure that the component doesn’t need to render after state or props are updated, you can return a false value. It is a great place to improve performance as it allows you to prevent a rerender if component receives new prop.

getSnapshotBeforeUpdate: Invoked right after a component render happens because of an update, before componentDidUpdate. Any value returned from this method will be passed to componentDidUpdate.

componentDidUpdate: Mostly it is used to update the DOM in response to prop or state changes.

componentWillUnmount: It will be used to cancel any outgoing network requests, or remove all event listeners associated with the component.

componentDidCatch: Used in error boundaries, which are components that implement this method. It allows the component to catch JavaScript errors anywhere in the child component tree (below this component), log errors, and display a UI with error information.

Which is the preferred option between callback refs and findDOMNode()?

Callback refs are preferred over the findDOMNode() API because findDOMNode() can interfere with certain React optimizations and future improvements.

// Legacy approach using findDOMNode()
class MyComponent extends Component {
  componentDidMount() {
    findDOMNode(this).scrollIntoView();
  }
 
  render() {
    return <div />;
  }
}
 
// Recommended approach using callback refs
class MyComponent extends Component {
  componentDidMount() {
    this.node.scrollIntoView();
  }
 
  render() {
    return <div ref={(node) => (this.node = node)} />;
  }
}
  • Callback refs provide a more flexible and recommended approach.

What is the difference between an element and a component in React?

An element is a plain JavaScript object that represents a DOM node or component. Elements are pure and never mutated, and are cheap to create.

A component is a function or class. Components can have state and take props as input and return an element tree as output (although they can represent generic containers or wrappers and don’t necessarily have to emit DOM). Components can initiate side effects in lifecycle methods (e.g., AJAX requests, DOM mutations, interfacing with 3rd party libraries) and may be expensive to create.

const Component = () => "Hello";
const componentElement = <Component />;
const domNodeElement = <div />;
  • Elements are immutable, plain objects that describe the DOM nodes or components you want to render.
  • Components can be either classes or functions, that take props as an input and return an element tree as the output.

What is the difference between HTML and React event handling?

In HTML, the attribute name is in all lowercase and is given a string invoking a function defined somewhere:

<button onclick="handleClick()"></button>

In React, the attribute name is camelCase and are passed the function reference inside curly braces:

<button onClick={handleClick} />

In HTML, false can be returned to prevent default behavior, whereas in React preventDefault has to be called explicitly.

<a href="#" onclick="console.log('The link was clicked.'); return false" />
function handleClick(e) {
  e.preventDefault();
  console.log("The link was clicked.");
}
  • HTML uses lowercase, React uses camelCase.

What are fragments?

Fragments allow React components to return multiple elements without an extra wrapper in the DOM. This reduces DOM nodes, improves performance, and simplifies CSS mechanisms such as tables, Flexbox, and Grid.

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}
 
// Short syntax supported by Babel 7
render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}
  • Fragments enable grouping of elements returned from a component without an additional DOM wrapper.

What are portals in React?

Portal are the recommended way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

ReactDOM.createPortal(child, container);

The first argument (child) is any renderable React child, such as an element, string, or fragment. The second argument (container) is a DOM element.

What is a stateful component in React?

A stateful component is a component whose behavior depends on its state. This means that two separate instances of the component if given the same props will not necessarily render the same output, unlike pure function components.

// Stateful class component
class App extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
  render() {
    // ...
  }
}
 
// Stateful function component
function App() {
  const [count, setCount] = useState(0);
  return; // ...
}
  • Stateful components have internal state that they depend on.
  • Stateful components are class components or function components that use stateful Hooks.
  • Stateful components have their state initialized in the constructor or with useState().

What is a stateless component?

A stateless component is a component whose behavior does not depend on its state. Stateless components can be either functional or class components. Stateless functional components are easier to maintain and test since they are guaranteed to produce the same output given the same props. Stateless functional components should be preferred when lifecycle hooks don’t need to be used.

  • Stateless components are independent of their state.
  • Stateless components can be either class or functional components.
  • Stateless functional components avoid the this keyword altogether.

How do you ensure methods have the correct this context in React component classes?

In JavaScript classes, methods are not bound by default, meaning their this context can change depending on how they are called. To fix this, you can use Function.prototype.bind() in the constructor to ensure this refers to the component instance.

constructor(props) {
  super(props);
  this.handleClick = this.handleClick.bind(this);
}
 
handleClick() {
  // Perform some logic
}
  • Alternatively, you can use the public class fields syntax to define methods with lexical this, preserving the component instance context:
handleClick = () => {
  console.log('this is:', this);
}
 
render() {
  return (
    <button onClick={this.handleClick}>
      Click me
    </button>
  );
}
  • Using inline arrow functions is another option but may lead to extra re-renders. For better performance, bind in the constructor or public class fields syntax is preferred.

What is the difference between HTML and React event handling?

In HTML, the attribute name is in all lowercase and is given a string invoking a function defined somewhere:

<button onclick="handleClick()"></button>

In React, the attribute name is camelCase and are passed the function reference inside curly braces:

<button onClick={handleClick} />

In HTML, false can be returned to prevent default behavior, whereas in React preventDefault has to be called explicitly.

<a href="#" onclick="console.log('The link was clicked.'); return false" />
function handleClick(e) {
  e.preventDefault();
  console.log("The link was clicked.");
}
  • HTML uses lowercase, React uses camelCase.