React Reference API

This documentation covers the essential concepts and components of the React Reference API, including components, JSX, props, state, context, hooks, forms, state management, composition vs inheritance, HOCs, render props, context API and Redux, refs, error boundaries, fragments, portals, profiler, server rendering, strict mode, concurrent mode, transitions, suspense, integrating with other libraries, advanced rendering techniques, optimizing performance, accessible forms, accessibility in React, debugging, security, tools and resources, and a detailed API reference.

Introduction to React Reference API

React is a powerful library for building user interfaces, particularly single-page applications where you need a fast, responsive UI. The React Reference API is a collection of functions, properties, and concepts that provide the core building blocks for React applications. Understanding the React Reference API is crucial for effectively using React and building robust applications.

What is the React Reference API?

The React Reference API is essentially a documentation guide that provides developers with the methods, hooks, and components available in React. It includes detailed explanations, examples, and usage guidelines for each part of the library.

Purpose of the React Reference API

The React Reference API serves as the official handbook for all React developers. It helps in learning how to use React's features effectively and efficiently by providing clear documentation, practical examples, and best practices.

React Components

Components are the building blocks of any React application. They allow you to split your UI into independent, reusable pieces and think about each piece in isolation.

Function Components

Function components are the simplest way to create components in React. They are JavaScript functions that return JSX.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

In this example, the Welcome function is a functional component. It accepts a props object that contains the properties passed to the component and returns a React element describing what should appear on the screen.

Class Components

Class components are more feature-rich than function components but can be more complex to write due to the additional boilerplate code.

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

In this snippet, the Welcome class extends React.Component and defines a render method that returns a React element.

Lifecycle Methods

Class components can have lifecycle methods that get called during different phases of their existence, such as mounting, updating, and unmounting the component.

Mounting

These methods are called when the component is being inserted into the DOM.

  • constructor(): A special method for creating and initializing an object.
  • render(): Required method. Examines this.props and this.state and returns a React element.
  • componentDidMount(): Invoked immediately after a component is mounted.
Updating

These are called when a component is being re-rendered as a result of changes to either its props or state.

  • shouldComponentUpdate(): Determines if the component should re-render when new props or state are received.
  • render(): Invoked when a component needs to be re-rendered.
  • componentDidUpdate(): Invoked immediately after updating occurs. Not called for the initial render.
Unmounting

This is called when a component is being removed from the DOM.

  • componentWillUnmount(): Cleanup method that allows you to perform necessary cleanup right before the component is unmounted from the DOM.
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 the component tree that crashed.

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    console.error("Caught an error", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

This ErrorBoundary class component will catch any errors in its child components and display "Something went wrong." if an error occurs.

JSX

JSX stands for JavaScript XML. It's a syntax extension for JavaScript that looks similar to HTML, and it helps you write JSX tags, which are then transformed into function calls.

What is JSX?

JSX provides an elegant syntax to write elements that describe how the UI should look. It is not required to use React, but JSX makes it easier to write and understand what your React components look like.

Writing JSX

JSX is syntactic sugar for function calls to React.createElement(component, props, ...children).

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

This JSX code is syntactic sugar for the following:

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

Embedding Expressions

You can embed any JavaScript expression inside curly braces in JSX.

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

In this example, the JavaScript variable name is embedded inside the JSX using curly braces, resulting in the element displaying "Hello, Josh Perez".

Specifying Attributes

You may use quotes to specify string literals as attributes.

const element = <div tabIndex="0"></div>;

You may also use curly braces to embed a JavaScript expression in an attribute.

const element = <img src={user.avatarUrl}></img>;

In this example, the src attribute of the img element is set using a JavaScript expression embedded in curly braces.

Specifying Children

If a tag is empty, you may close it immediately with />, just like XML.

const element = <img src={user.avatarUrl} />;

JSX tags can contain children.

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

Preventing Injection Attacks

React DOM escapes any values embedded in JSX before rendering them. This helps prevent XSS (cross-site scripting) attacks by sanitizing the input data.

const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;

In this example, response.potentiallyMaliciousInput is sanitized before being rendered inside the h1 tag.

Props

Props are read-only in React. This means that a component can only read the props passed to it and cannot modify them.

What are Props?

Props are short for properties. They are the arguments passed into React components to customize and manipulate their behavior.

Passing Props

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;

In this example, the Welcome component is passed a name prop with the value "Sara". The component reads the value of the name prop and returns a React element displaying "Hello, Sara".

Default Props

Default props can be defined for a component.

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Greeting.defaultProps = {
  name: 'Stranger'
};

In this example, if no name prop is passed to the Greeting component, it will default to "Stranger".

PropTypes

PropTypes is a library that helps type-checking the props passed to components.

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};

In this example, PropTypes.string ensures that the name prop must be a string. If name is not a string, a warning will be shown in the JavaScript console.

State

State is a feature in React that enables components to store data and re-render when the data changes.

What is State?

State is an object that holds the data that needs to be shared and changed between the various functions of a React component.

Adding Local State to a Class

You can add local state to a class by declaring a state property in the constructor of the class.

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

In this example, the Clock class component initializes its state in its constructor with a date property. The render method then accesses the state value using this.state.date and displays the current time.

State Updates Are Merged

When you want to update the state, you should not modify the state directly.

this.setState({comment: 'Hello'});

In this example, setState is used to update the comment property of the state object.

State Updates May Be Asynchronous

React may batch multiple setState() calls into a single update for performance reasons.

this.setState({quantity: this.state.quantity + 1});

For code that relies on previous state, such as an increment counter, use the function form of setState.

this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

In this example, the function form of setState ensures that the increment operation is based on the previous state.

Using Functional State Updates

When state updates should be based on the previous state, use a function to perform the update instead of using an object.

this.setState((prevState) => ({
  count: prevState.count + 1
}));

In this example, the count property of the state object is incremented by 1 based on the previous state.

Context

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

What is Context?

Context allows you to define a value that is accessible to all components in the tree, without having to pass props explicitly.

When to Use Context?

Context is useful when some data needs to be accessible by many components at different nesting levels. Examples include:

  • Authentication status
  • Theme (light/dark)
  • Location settings

Before You Use Context

Before using context, consider other simpler solutions, such as lifting state up or component composition.

API

React.createContext

Creates a Context object. When React renders a context provider, it reads the nearest current value of that context from the closest matching Provider above and uses it to render the children.

const MyContext = React.createContext(defaultValue);

In this example, React.createContext creates a Context object with a default value.

Context.Provider

A Provider component that accepts a value prop to be passed to consuming components that are descendants of this Provider.

<MyContext.Provider value={someValue}>
  <ChildComponent />
</MyContext.Provider>

In this code snippet, the MyContext.Provider component provides the someValue to all descendants of the ChildComponent.

Context.Consumer

A Consumer component that subscribes to context changes. This lets you subscribe to context within a function component.

class MyClass extends React.Component {
  render() {
    return (
      <MyContext.Consumer>
        {value => /* render something based on the context value */}
      </MyContext.Consumer>
    );
  }
}

In this example, the MyContext.Consumer subscribes to MyContext and renders something based on the context value.

Context.displayName

Sets the display name for debugging contexts using React DevTools.

const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';

In this snippet, MyContext is given a display name of MyDisplayName for debugging purposes.

Hooks

Hooks allow you to use state and other React features without writing a class.

Introduction to Hooks

Hooks let you use state and other React features without writing a class.

State Hook

Declaring a State Variable

You can use the useState hook to add state to function components.

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

In this example, useState initializes the count state variable to 0.

Reading State

States can be used in JSX as if they were regular variables.

function Example() {
  const [count, setCount] = useState(0);
  return <p>You clicked {count} times</p>;
}

In this code, count is used as a regular variable inside JSX to display the count.

Updating State

You can use the set function returned by useState to update the state.

function Example() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      Click me
    </button>
  );
}

In this example, setCount is used to update the count state variable when the button is clicked.

Effect Hook

Side Effects Without Hooks

In class components, side effects are typically performed in componentDidMount, componentDidUpdate, and componentWillUnmount. These lifecycle methods perform side effects, and it's easy to forget to handle all cases.

Effect Hook Explanation

The Effect Hook lets you perform side effects in function components.

import React, { useEffect } from 'react';

function Example() {
  useEffect(() => {
    // This effect runs after every render, including the first one
    document.title = `You clicked ${count} times`;
  });
  return <p>You clicked {count} times</p>;
}

In this example, the useEffect hook updates the document title after every render, including the first one.

Tips for Using Effects

Optimizing Performance by Skipping Effects

You can tell React to skip applying an effect if certain values haven't changed.

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes

In this code, the effect will only re-run if the count value changes.

Rules of Hooks

Only Call Hooks at the Top Level

Don't call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function.

Only Call Hooks from React Functions

Don't call Hooks from regular JavaScript functions. Instead, call Hooks from React function components or custom Hooks.

Forms

Forms in React are a bit different from other DOM elements because form elements in HTML maintain their own state that is mutable.

Controlled Components

A controlled component is one whose value is controlled by React state. To make a form element a controlled component, you need to do two things:

  • Control the component's state.
  • Pass a callback function to update the state.

Input Tags

textarea Tag

Use the value attribute to set the contents of a textarea.

<textarea value={this.state.value} onChange={this.handleChange} />

In this example, the textarea content is controlled by the value attribute, which is tied to the state.

select Tag

You can create a select item by using the value attribute.

<select value={this.state.value} onChange={this.handleChange}>
  <option value="grapefruit">Grapefruit</option>
  <option value="lime">Lime</option>
  <option selected value="coconut">Coconut</option>
  <option value="mango">Mango</option>
</select>

In this example, the select item is controlled by the value attribute, which is tied to the state.

Handling Multiple Inputs

Control multiple inputs by adding a name attribute to each input and letting the handler function determine which state property to update.

class Reservation extends React.Component {
  state = {
    isGoing: true,
    numberOfGuests: 2
  };

  handleChange = (event) => {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  };

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleChange} />
        </label>
      </form>
    );
  }
}

In this example, the handleChange method updates the appropriate state field based on the name attribute of the input elements.

Controlled Input Null Value

Specifying a value for the controlled input will prevent the user from changing the input unless you intend to.

render() {
  return (
    <input value={this.state.value} onChange={this.handleChange} />
  );
}

In this example, the value attribute is set to this.state.value, making the input controlled.

State Management

Lifting State Up

Sometimes, you need the state of several components to reflect the same data. It is recommended to lift the shared state up to their closest common ancestor.

Thinking in React

  1. Break the UI into a component hierarchy.
  2. Build a static version in React.
  3. Identify the minimal (but complete) representation of UI state.
  4. Identify where the state should live.
  5. Add inverse data flow.

Composition vs Inheritance

Containment

Containment is a design pattern where there is no need to know the children of a component in advance.

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

In this example, FancyBorder uses {props.children} to render anything inside the child component(s).

Specialization

Specialization is a concept where a more specialized component is a special case of a more generic one.

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

In this example, the Dialog component is a specialization of the FancyBorder component, passing additional props like title and message.

Higher-Order Components (HOCs)

A higher order component is a function that takes a component and returns a new component.

Use HOCs for Cross-Cutting Concerns

HOCs are used to share common functionality between components.

Caveats

Don’t Use HOCs Inside the Render Method

Using HOCs inside the render method will cause the component to unmount on every update.

Static Methods Must Be Copied Over

Static methods must be copied onto the container component when you use HOCs.

Refs Aren’t Passed Through

Refs do not get passed through. Higher-order components (HOCs) imperatively modify the component to add extra behavior. However, another common use case for refs is to access the underlying DOM element or the inner component instance.

Conventional Props

render props

The render prop is a technique for sharing code between React components using a propagation pattern where you pass a function as a prop to a component that calls that function instead of implementing render logic itself.

props.children

The most common way for components to render children in their output is via the special children prop.

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>
    </FancyBorder>
  );
}

In this example, WelcomeDialog passes its children to FancyBorder through props.children.

Render Props

Using Props to Pass a Render Function

class Cat extends React.Component {
  render() {
    return <h1>{this.props.render(this.props.cat)}</h1>;
  }
}

class Mouse extends React.Component {
  constructor(props) {
    super(props);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove = (event) => {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>
        {/*
          Instead of providing a static representation of what <MouseWithCat>
          renders, we provide a function that knows about both render props
          and the render prop.
        */}
        {this.props.render(this.state)}
      </div>
    );
  }
}

function App() {
  return (
    <div>
      <h1>Move the mouse around!</h1>
      <Mouse render={
        mouse => <Cat mouse={mouse} />
      }/>
    </div>
  );
}

In this example, the Mouse component uses the render prop to pass mouse state to the Cat component.

Using Render Props for Cross-Cutting Concerns

Render props can also be used for cross-cutting concerns like user authentication, window dimensions, etc.

Caveats

Be Careful When Using Render Props with React.PureComponent

If you are using the render prop and the PureComponent class, it might not work as expected.

Context API and Redux

Context API

Creating Context

const MyContext = React.createContext(defaultValue);

In this example, a new context object MyContext is created with a default value.

Context.Provider

<MyContext.Provider value={someValue}>
  <ChildComponent />
</MyContext.Provider>

In this snippet, someValue is passed down to the child components.

Context.Consumer

<MyContext.Consumer>
  {value => /* render something based on the value */}
</MyContext.Consumer>

In this example, the Context.Consumer subscribes to MyContext and renders something based on the context value.

Context.displayName

const MyContext = React.createContext(defaultValue);
MyContext.displayName = 'MyDisplayName';

In this example, MyContext is given a display name of MyDisplayName.

React Refs

Creating Refs

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

In this example, this.myRef is created in the constructor and attached to a div in the render method.

Accessing Refs

You can access the current property of the ref to get the actual DOM node or React element.

class MyComponent extends React.Component {
  myRef = React.createRef();

  componentDidMount() {
    // Access the DOM node
    console.log(this.myRef.current);
  }

  render() {
    return <div ref={this.myRef} />;
  }
}

In this snippet, this.myRef.current is used to access the DOM node after the component is mounted.

Adding a Ref to a Class Component

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // Create a ref to store the textInput DOM element
    this.textInput = React.createRef();
  }

  focusTextInput = () => {
    // Explicitly focus the text input using the raw DOM API
    this.textInput.current.focus();
  }

  render() {
    // Use the `ref` callback attribute to store a reference to the text input DOM element
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

In this example, the TextInput is focused via the ref when the button is clicked.

Callback Refs

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = null;

    this.setTextInputRef = element => {
      this.textInput = element;
    };
  }

  focusTextInput = () => {
    if (this.textInput) this.textInput.focus();
    // Explicitly focus the text input using the raw DOM API
  }

  render() {
    return (
      <div>
        <input
          type="text"
          ref={this.setTextInputRef} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

In this example, a callback ref is used to set the textInput property of the component to the DOM node when it mounts.

Forwarding Refs

function FancyButton(props) {
  return (
    <button className="FancyButton">
      {props.children}
    </button>
  );
}

In this example, a standard button component is created.

Forwarding Refs in Higher Order Components
function logProps(WrappedComponent) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props: ', this.props);
    }

    render() {
      // Wraps the input component in a div with a friendly display name.
      return <WrappedComponent {...this.props} />;
    }
  }

  return LogProps;
}

In this snippet, a higher-order component that logs props changes is created.

Error Boundaries

Catching Errors with Error Boundaries

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // 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
    logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

In this example, an ErrorBoundary reacts to errors when rendering, in lifecycle methods, or in the constructors of any of its children.

How Error Boundaries Work

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

Where to Place Error Boundaries

Consider where in your component tree should have error boundaries. Error boundaries work like catch in JavaScript — they catch errors that happen anywhere in their child component tree, not in themselves.

New Lifecycle Methods

  • static getDerivedStateFromError(error)
  • componentDidCatch(error, info)

Fragments

Why Fragments Are Useful

You can return a single element in a component’s render method. However, sometimes you want to group a list of children without adding extra nodes to the DOM.

Keyed Fragments

function ItemList(props) {
  return (
    <React.Fragment>
      {props.items.map(item => (
        // Without the `key`, React will give a key warning
        <li key={item.id}>{item.text}</li>
      ))}
    </React.Fragment>
  );
}

In this example, React.Fragment is used to wrap the list items without adding an additional DOM node.

Creating Fragments

function Table() {
  return (
    <table>
      <tr>
        <Column />
      </tr>
    </table>
  );
}

function Column() {
  return (
    <React.Fragment>
      <td>Hello</td>
      <td>World</td>
    </React.Fragment>
  );
}

In this code snippet, React.Fragment is used to group multiple td elements without adding an additional DOM node.

Portals

What Are Portals?

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

How to Use Portals

const portalRoot = document.getElementById('portal-root');
class Modal extends React.Component {
  componentDidMount() {
    this.mountNode = document.createElement('div');
    portalRoot.appendChild(this.mountNode);
  }

  componentWillUnmount() {
    portalRoot.removeChild(this.mountNode);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.mountNode
    );
  }
}

In this example, the Modal component uses ReactDOM.createPortal to render its children into a div with the id portal-root.

Profiler

Purpose of Profiler

Profiler is a component that measures the performance of rendering in a subtree. It helps in identifying performance issues in the component that slow down the app.

onRender Callback

The onRender prop is a callback for when a component renders. It is fired after the component tree has committed an update.

<Profiler id="panel" onRender={callback}>
  <Panel />
</Profiler>

In this example, the callback function is called when the Panel component renders.

Profiler Nesting

<Profiler id="Outer">
  <div>
    <Profiler id="Inner">
      <p>Hello World</p>
    </Profiler>
  </div>
</Profiler>

In this example, the Profiler components are nested, allowing you to measure performance at different levels of the component hierarchy.

Server Rendering

Server Rendering with Data Requirements

Server-side rendering can boost your app's performance by rendering components on the server and sending the HTML early.

Data Fetching

You can fetch data in the server and pass it to your React components as props.

Strict Mode

Enabling Strict Mode

<StrictMode>
  <App />
</StrictMode>

In this snippet, the App component is wrapped in StrictMode, enabling the strict mode in the entire app.

Strict Mode’s Behavior

  • Identifies components with unsafe lifecycle methods.
  • Warns about legacy string ref API usage.
  • Warns about deprecated findDOMNode() usage.

Concurrent Mode

Introduction to Concurrent Mode

Concurrent Mode is a set of features that allow React apps to render updates to the user interface in a more flexible way with more granular control.

Why Concurrent Mode?

  • Enables React to interrupt and resume rendering tasks when it detects high-priority updates.
  • Includes features like Suspense and Transitions.

Transitions

What is a Transition?

Transitions are a feature in Concurrent Mode that allows components to opt out of participating in a concurrent render and be updated as a group after a high-priority interaction has completed.

Start a Transition

import { startTransition } from 'react';

startTransition(() => {
  someAction();
});

In this example, the someAction function is wrapped a startTransition, allowing it to participate in a transition.

Updating the UI During a Transition

You can use the isPending hook to track transitions.

import { useTransition } from 'react';

function TransitionComponent({ isPending }) {
  return isPending ? <LoadingSpinner /> : <MainContent />;
}

In this example, a LoadingSpinner is shown if the transition is pending, otherwise MainContent is shown.

Understanding the Animation

React.memo and useCallback are used to optimize performance during transitions.

React.memo

const Button = React.memo(function Button({ value, onClick }) {
  return <button onClick={onClick}>{value}</button>;
});

In this example, React.memo is used to prevent unnecessary re-renders of the Button component.

useCallback

const memoizedValue = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b]
);

In this example, useCallback is used to memoize a callback function.

useDeferredValue

const deferredValue = useDeferredValue(someValue);

In this example, useDeferredValue wraps a value and returns a new value that will be the previous one until the concurrent render has completed.

Examples of useDeferredValue

const deferredValue = useDeferredValue(value);

function List() {
  // The deferred value will update later, allowing the text field to update immediately.
  return <ExpensiveList items={deferredValue} />;
}

In this example, useDeferredValue is used to defer the update of items in the List component while the text field is updated immediately.

Suspense

Suspense for Code Splitting

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

In this example, OtherComponent is lazily loaded and a fallback UI is displayed while it is being loaded.

Using Suspense for Data Fetching

function ProfilePage() {
  const user = useProfileData(userID);

  return (
    <Suspense fallback={<Spinner />}>
      <ProfileDetails user={user} />
    </Suspense>
  );
}

In this example, the user data is fetched asynchronously, and a Spinner is shown during the loading state.

Revealing Nested Suspense

const MainLayout = () => (
  <div>
    <Header />
    <Suspense fallback={<LoadingSpinner />}>
      <section>
        <Suspense fallback={<LoadingBar />}>
          <ProfileComponent />
        </Suspense>
        <Suspense fallback={<LoadingBar />}>
          <PhotosComponent />
        </Suspense>
      </section>
    </Suspense>
    <Footer />
  </div>
);

function ProfileComponent() {
  const user = useProfileData(userID);
  return <h1>{user.name}</h1>;
}

In this example, nested Suspense components are used to reveal different parts of the UI at different times.

React Refs

Creating Refs

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  render() {
    return <div ref={this.myRef} />;
  }
}

In this example, a ref is created in the constructor and attached to a div in the render method.

Accessing Refs

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  componentDidMount() {
    // Access the DOM node
    console.log(this.myRef.current);
  }

  render() {
    return <div ref={this.myRef} />;
  }
}

In this snippet, the this.myRef.current is used to access the DOM node after the component is mounted.

Adding a Ref to a Class Component

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();
  }

  focusTextInput = () => {
    if (this.textInput.current) this.textInput.current.focus();
  }

  render() {
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

In this example, a ref is used to focus the text input when the button is clicked.

Callback Refs

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = null;
    this.setTextInputRef = element => {
      this.textInput = element;
    };
  }

  focusTextInput = () => {
    if (this.textInput) this.textInput.focus();
  }

  render() {
    return (
      <div>
        <input
          type="text"
          ref={this.setTextInputRef} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

In this example, a callback ref is used to set the textInput property of the component to the DOM node when it mounts.

Forwarding Refs

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

In this code snippet, the FancyButton component forwards its ref to the underlying button element.

Forwarding Refs in Higher Order Components
function logProps(WrappedComponent) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props: ', this.props);
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  return LogProps;
}

In this example, the logProps HOC logs when its wrapped component's props change.

Fragments

Why Fragments Are Useful

Fragments are useful for grouping elements without adding extra DOM elements.

Keyed Fragments

function ItemList(props) {
  return (
    <React.Fragment>
      {props.items.map(item => (
        // Without the `key`, React will give a key warning
        <li key={item.id}>{item.text}</li>
      ))}
    </React.Fragment>
  );
}

In this example, React.Fragment is used to wrap the list items without adding an additional DOM node.

Creating Fragments

function Table() {
  return (
    <table>
      <tr>
        <Column />
      </tr>
    </table>
  );
}

function Column() {
  return (
    <React.Fragment>
      <td>Hello</td>
      <td>World</td>
    </React.Fragment>
  );
}

In this example, React.Fragment is used to group the td elements without adding an additional DOM node.

Portals

What Are Portals?

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

How to Use Portals

const portalRoot = document.getElementById('portal-root');
class Modal extends React.Component {
  componentDidMount() {
    this.mountNode = document.createElement('div');
    portalRoot.appendChild(this.mountNode);
  }

  componentWillUnmount() {
    portalRoot.removeChild(this.mountNode);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.mountNode
    );
  }
}

In this example, the Modal component uses ReactDOM.createPortal to render its children into a div with the id portal-root.

Profiler

Purpose of Profiler

The Profiler measures the performance of rendering in a subtree. It helps in identifying performance issues in the component that slow down the app.

onRender Callback

The onRender prop is a callback for when a component renders.

<Profiler id="navigation" onRender={callback}>
  <Navigation />
</Profiler>

In this example, the callback function is called when the Navigation component renders.

Profiler Nesting

<Profiler id="panel">
  <div>
    <Profiler id="inner">
      <p>Hello</p>
    </Profiler>
    <Profiler id="button">
      <button>Click me</button>
    </Profiler>
  </div>
</Profiler>

In this example, Profiler components are nested, allowing you to measure performance at different levels of the component hierarchy.

Server Rendering

Server Rendering with Data Requirements

Server-side rendering can boost your app's performance by rendering components on the server and sending the HTML early.

Data Fetching

You can fetch data in the server and pass it to your React components as props.

Strict Mode

Enabling Strict Mode

<StrictMode>
  <App />
</StrictMode>

In this code snippet, the App component is wrapped in StrictMode, enabling the strict mode in the entire app.

Strict Mode’s Behavior

  • Identifies components with unsafe lifecycle methods.
  • Warns about legacy string ref API usage.
  • Warns about deprecated findDOMNode() usage.

Concurrent Mode

Introduction to Concurrent Mode

Concurrent Mode is a set of features that allow React apps to render updates to the user interface in a more flexible way with more granular control.

Why Concurrent Mode?

  • Enables React to interrupt and resume rendering tasks when it detects high-priority updates.
  • Includes features like Suspense and Transitions.

Transitions

What is a Transition?

Transitions are a feature in Concurrent Mode that allows components to opt out of participating in a concurrent render and be updated as a group after a high-priority interaction has completed.

Start a Transition

import { startTransition } from 'react';

startTransition(() => {
  someAction();
});

In this example, the someAction function is wrapped a startTransition, allowing it to participate in a transition.

Updating the UI During a Transition

You can use the isPending hook to track transitions.

import { useTransition } from 'react';

const deferredValue = useDeferredValue(value);

function List() {
  // The deferred value will update later, allowing the text field to update immediately.
  return <ExpensiveList items={deferredValue} />;
}

In this example, useDeferredValue wraps a value and returns a new value that will be the previous one until the concurrent render has completed.

Understanding the Animation

React.memo and useCallback are used to optimize performance during transitions.

React.memo

const Button = React.memo(function Button({ value, onClick }) {
  return <button onClick={onClick}>{value}</button>;
});

In this example, React.memo is used to prevent unnecessary re-renders of the Button component.

useCallback

const memoizedValue = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b]
);

In this example, useCallback is used to memoize a callback function.

useDeferredValue

const deferredValue = useDeferredValue(someValue);

In this example, useDeferredValue wraps a value and returns a new value that will be the previous one until the concurrent render has completed.

Examples of useDeferredValue

const deferredValue = useDeferredValue(value);

function List() {
  // The deferred value will update later, allowing the text field to update immediately.
  return <ExpensiveList items={deferredValue} />;
}

In this example, useDeferredValue is used to defer the update of items in the List component while the text field is updated immediately.

Suspense

Suspense for Code Splitting

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

In this example, OtherComponent is lazily loaded, and a fallback UI is displayed while it is being loaded.

Using Suspense for Data Fetching

function ProfilePage() {
  const user = useProfileData(userID);
  return (
    <Suspense fallback={<Spinner />}>
      <ProfileDetails user={user} />
    </Suspense>
  );
}

In this example, the user data is fetched asynchronously, and a Spinner is shown during the loading state.

Revealing Nested Suspense

const MainLayout = () => (
  <div>
    <Header />
    <Suspense fallback={<LoadingSpinner />}>
      <section>
        <Suspense fallback={<LoadingBar />}>
          <ProfileComponent />
        </Suspense>
        <Suspense fallback={<LoadingBar />}>
          <PhotosComponent />
        </Suspense>
      </section>
    </Suspense>
    <Footer />
  </div>
);

function ProfileComponent() {
  const user = useProfileData(userID);
  return <h1>{user.name}</h1>;
}

In this example, nested Suspense components are used to reveal different parts of the UI at different times.

Integrating with Other Libraries

Writing Reusable Components with Props and Compose

Higher-Order Components and Render Props

Higher-order components (HOCs) and render props are powerful patterns for code reuse in React. They help in abstracting logic from components.

const EnhancedComponent = withLogging(MyComponent);

In this example, the withLogging HOC is used to add logging to MyComponent.

Advanced Rendering Techniques

React.lazy

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return <OtherComponent />;
}

In this example, OtherComponent is lazily loaded.

React.Suspense

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />
    </Suspense>
  );
}

In this snippet, the MyComponent component uses Suspense to display a loading message while OtherComponent is being loaded lazily.

Code Splitting with React.lazy

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

In this example, OtherComponent is lazily loaded and a fallback UI is displayed while it is being loaded.

Named Exports

You can use named exports when exporting multiple components.

export { ThingOne, ThingTwo };

In this example, ThingOne and ThingTwo can be imported and used in other parts of the app.

Optimizing Performance

Virtualize Long Lists

Use libraries like react-window or react-virtualized to virtualize long lists.

Avoid Inline Functions

Avoid using inline functions as they can prevent optimization in some circumstances.

Avoid Inline Object Literals

Avoid creating new objects or arrays inline, as this can negate some optimizations.

Accessible Forms

Labeling Controls

<label htmlFor="namedInput">Name:</label>
<input id="namedInput" type="text" name="name" />

In this example, the label element is associated with the input element using the for attribute.

Managing Focus

Use the ref attribute to manage focus.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }

  componentDidMount() {
    this.inputRef.current.focus();
  }

  render() {
    return <input ref={this.inputRef} />;
  }
}

In this example, the input is focused when the component is mounted.

Handling Key Events

Listen to keyboard events using event listeners.

class MyComponent extends React.Component {
  handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      console.log('Enter pressed');
    }
  }

  render() {
    return (
      <input
        type="text"
        onKeyDown={this.handleKeyDown} />
    );
  }
}

In this example, the handleKeyDown method handles the Enter key event.

Accessibility in React

Naming Conventions

Follow naming conventions such as using aria-label for screen readers.

DOM Representation

React generates a DOM where you can manage accessibility features.

Forms

Labels

Use labels for form controls to help screen readers map form controls to the form labels.

Dynamic Roles

You can use the role attribute for dynamic roles.

ARIA Attributes

Use ARIA attributes to convey additional semantics to screen readers.

Debugging

Profiling the Performance of a Component

Use the Chrome React DevTools Profiler to profile the performance of a component.

Profiling Production Builds

You can profile the performance of a component in production builds using React Profiler.

Identifying Resource Heavy Components

Identify the components that consume the most resources using profiling tools.

Identifying Concurrent Mode Issues

Use the React Profiler to identify issues in Concurrent Mode.

Security

JSX Injection Attacks

JSX code is safe from XSS attacks. React DOM escapes any values embedded in JSX before rendering them to the DOM, preventing code injection attacks.

Protecting Your Application from XSS Attacks

Always sanitize and validate any input data to protect your application from XSS attacks.

Avoiding Risks with Injection Attacks

Avoid using innerHTML or related properties that can lead to injection attacks.

Tools and Resources

Official Documentation

Refer to the official React documentation.

Community Resources

Join the React community to learn more and get help.

Courses and Tutorials

Take online courses and tutorials to deepen your understanding of React.

API Reference

React

ReactDOM

  • ReactDOM.render()
  • ReactDOM.hydrate()
  • ReactDOM.unmountComponentAtNode()
  • ReactDOM.createPortal()

ReactDOMServer

  • ReactDOMServer.renderToString()
  • ReactDOMServer.renderToStaticMarkup()

ReactDOMClient

  • ReactDOM.createRoot()

Concurrent Mode APIs

  • React.lazy()
  • Suspense
  • React.memo()
  • useDeferredValue()
  • useTransition()
  • Profiler
  • startTransition()

By understanding and effectively using the React Reference API, you can build robust and efficient web applications with better performance and maintainability. Each concept and component covered in this documentation serves a specific purpose, making React a powerful tool for building complex UIs efficiently.