Frontend / React / react_fragment.md

React Fragment

Updated 3 interview angles 7 min read source
On this page9
  1. Table of Contents
  2. What is React Fragment?
  3. Fragment Syntax
  4. Common Use Cases
  5. Advanced Fragment Patterns
  6. Best Practices
  7. Common Interview Questions
  8. Summary
  9. Interview angle

React Fragment

React Fragment is a way to group multiple elements without adding extra DOM nodes, providing a cleaner way to return multiple elements from components.

Table of Contents

What is React Fragment?

React Fragment is a special component that allows you to group multiple elements without creating an additional DOM node.

Key Concepts:

  • No extra DOM node: Groups elements without wrapper div
  • Performance benefit: Reduces DOM complexity
  • Clean JSX: Avoids unnecessary wrapper elements
  • Multiple syntaxes: <> shorthand and <React.Fragment>

Problem Fragment Solves:

javascript
// Before Fragment: Extra div wrapper
function App() {
  return (
    <div> {/* Unnecessary wrapper */}
      <h1>Title</h1>
      <p>Paragraph</p>
      <button>Click me</button>
    </div>
  );
}

// With Fragment: No extra wrapper
function App() {
  return (
    <>
      <h1>Title</h1>
      <p>Paragraph</p>
      <button>Click me</button>
    </>
  );
}

Fragment Syntax

1. Shorthand Syntax:

javascript
// Short syntax (most common)
function Component() {
  return (
    <>
      <h1>Hello</h1>
      <p>World</p>
    </>
  );
}

// Renders as:
// <h1>Hello</h1>
// <p>World</p>
// (No wrapper element)

2. Full Syntax:

javascript
// Full syntax with React.Fragment
import React from 'react';

function Component() {
  return (
    <React.Fragment>
      <h1>Hello</h1>
      <p>World</p>
    </React.Fragment>
  );
}

// Or with destructured import
import React, { Fragment } from 'react';

function Component() {
  return (
    <Fragment>
      <h1>Hello</h1>
      <p>World</p>
    </Fragment>
  );
}

3. Fragment with Keys:

javascript
// Fragment with key prop (only available in full syntax)
function List({ items }) {
  return (
    <React.Fragment>
      {items.map(item => (
        <React.Fragment key={item.id}>
          <h3>{item.title}</h3>
          <p>{item.description}</p>
        </React.Fragment>
      ))}
    </React.Fragment>
  );
}

// Usage
const items = [
  { id: 1, title: 'Item 1', description: 'Description 1' },
  { id: 2, title: 'Item 2', description: 'Description 2' }
];

function App() {
  return <List items={items} />;
}

Common Use Cases

1. Returning Multiple Elements:

javascript
// Component that needs to return multiple elements
function UserProfile({ user }) {
  return (
    <>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
      <p>{user.role}</p>
      <button>Edit Profile</button>
    </>
  );
}

// Without Fragment, you'd need a wrapper div
function UserProfileWithDiv({ user }) {
  return (
    <div className="user-profile"> {/* Extra wrapper */}
      <h2>{user.name}</h2>
      <p>{user.email}</p>
      <p>{user.role}</p>
      <button>Edit Profile</button>
    </div>
  );
}

2. Conditional Rendering:

javascript
// Conditional rendering with Fragment
function ConditionalContent({ showHeader, showFooter, children }) {
  return (
    <>
      {showHeader && <header>Header Content</header>}
      <main>{children}</main>
      {showFooter && <footer>Footer Content</footer>}
    </>
  );
}

// Usage
function App() {
  return (
    <ConditionalContent showHeader={true} showFooter={false}>
      <p>Main content</p>
    </ConditionalContent>
  );
}

3. List Rendering:

javascript
// Rendering lists without wrapper
function TodoList({ todos }) {
  return (
    <>
      {todos.map(todo => (
        <div key={todo.id} className="todo-item">
          <span>{todo.text}</span>
          <button>Delete</button>
        </div>
      ))}
    </>
  );
}

// Alternative with Fragment for each item
function TodoListWithFragment({ todos }) {
  return (
    <>
      {todos.map(todo => (
        <React.Fragment key={todo.id}>
          <span>{todo.text}</span>
          <button>Delete</button>
        </React.Fragment>
      ))}
    </>
  );
}

4. Table Structures:

javascript
// Table with Fragment (no extra wrapper)
function TableRow({ cells }) {
  return (
    <>
      {cells.map((cell, index) => (
        <td key={index}>{cell}</td>
      ))}
    </>
  );
}

// Usage in table
function DataTable({ data }) {
  return (
    <table>
      <tbody>
        {data.map((row, rowIndex) => (
          <tr key={rowIndex}>
            <TableRow cells={row} />
          </tr>
        ))}
      </tbody>
    </table>
  );
}

5. Form Layouts:

javascript
// Form with multiple elements
function FormField({ label, error, children }) {
  return (
    <>
      <label>{label}</label>
      {children}
      {error && <span className="error">{error}</span>}
    </>
  );
}

// Usage
function ContactForm() {
  return (
    <form>
      <FormField label="Name" error="Name is required">
        <input type="text" />
      </FormField>

      <FormField label="Email">
        <input type="email" />
      </FormField>

      <FormField label="Message">
        <textarea />
      </FormField>
    </form>
  );
}

Advanced Fragment Patterns

1. Fragment with Conditional Logic:

javascript
// Complex conditional rendering
function ComplexComponent({ user, showDetails, showActions }) {
  return (
    <>
      <h2>{user.name}</h2>

      {showDetails && (
        <>
          <p>Email: {user.email}</p>
          <p>Role: {user.role}</p>
          <p>Department: {user.department}</p>
        </>
      )}

      {showActions && (
        <>
          <button>Edit</button>
          <button>Delete</button>
          <button>Archive</button>
        </>
      )}
    </>
  );
}

2. Fragment with HOCs:

javascript
// HOC that returns multiple elements
function withHeaderAndFooter(WrappedComponent) {
  return function EnhancedComponent(props) {
    return (
      <>
        <header>Header from HOC</header>
        <WrappedComponent {...props} />
        <footer>Footer from HOC</footer>
      </>
    );
  };
}

// Usage
const EnhancedComponent = withHeaderAndFooter(MyComponent);

3. Fragment with Context:

javascript
// Context provider with Fragment
const ThemeContext = React.createContext('light');

function ThemeProvider({ children, theme }) {
  return (
    <>
      <ThemeContext.Provider value={theme}>
        {children}
      </ThemeContext.Provider>
      <style>{`
        :root {
          --theme: ${theme};
        }
      `}</style>
    </>
  );
}

4. Fragment with Portals:

javascript
// Component that renders to multiple places
function ModalWithBackdrop({ children, isOpen }) {
  if (!isOpen) return null;

  return (
    <>
      {ReactDOM.createPortal(
        <div className="backdrop" />,
        document.body
      )}
      {ReactDOM.createPortal(
        <div className="modal">{children}</div>,
        document.body
      )}
    </>
  );
}

5. Fragment with Error Boundaries:

javascript
// Error boundary with Fragment
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

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

  render() {
    if (this.state.hasError) {
      return (
        <>
          <h2>Something went wrong</h2>
          <button onClick={() => this.setState({ hasError: false })}>
            Try again
          </button>
        </>
      );
    }

    return this.props.children;
  }
}

Best Practices

1. Use Shorthand When Possible:

javascript
// Good: Use shorthand for simple cases
function SimpleComponent() {
  return (
    <>
      <h1>Title</h1>
      <p>Content</p>
    </>
  );
}

// Good: Use full syntax when you need keys
function ListWithKeys({ items }) {
  return (
    <>
      {items.map(item => (
        <React.Fragment key={item.id}>
          <h3>{item.title}</h3>
          <p>{item.description}</p>
        </React.Fragment>
      ))}
    </>
  );
}

2. Don’t Overuse Fragments:

javascript
// Good: Use Fragment when you need multiple elements
function GoodComponent() {
  return (
    <>
      <h1>Title</h1>
      <p>Content</p>
    </>
  );
}

// Bad: Don't use Fragment for single element
function BadComponent() {
  return (
    <>
      <h1>Title</h1>
    </>
  );
  // Should just return <h1>Title</h1>
}

3. Consider Semantic HTML:

javascript
// Good: Use semantic elements when appropriate
function GoodLayout() {
  return (
    <>
      <header>Header</header>
      <main>Main content</main>
      <footer>Footer</footer>
    </>
  );
}

// Bad: Don't use Fragment when semantic wrapper makes sense
function BadLayout() {
  return (
    <>
      <h1>Header</h1>
      <p>Main content</p>
      <p>Footer</p>
    </>
  );
  // Should use semantic elements or a wrapper
}

4. Handle Keys Properly:

javascript
// Good: Use keys with Fragment when needed
function GoodList({ items }) {
  return (
    <>
      {items.map(item => (
        <React.Fragment key={item.id}>
          <h3>{item.title}</h3>
          <p>{item.description}</p>
        </React.Fragment>
      ))}
    </>
  );
}

// Bad: Missing keys can cause issues
function BadList({ items }) {
  return (
    <>
      {items.map(item => (
        <>
          <h3>{item.title}</h3>
          <p>{item.description}</p>
        </>
      ))}
    </>
  );
}

5. Consider Performance:

javascript
// Good: Fragment reduces DOM nodes
function EfficientComponent() {
  return (
    <>
      <h1>Title</h1>
      <p>Content</p>
    </>
  );
  // Only 2 DOM nodes: h1 and p
}

// Bad: Wrapper div adds extra DOM node
function InefficientComponent() {
  return (
    <div>
      <h1>Title</h1>
      <p>Content</p>
    </div>
  );
  // 3 DOM nodes: div, h1, and p
}

Common Interview Questions

Q: What is React Fragment?

  • A way to group multiple elements without adding extra DOM nodes.

Q: What are the different ways to write Fragment?

  • Shorthand syntax <> and full syntax <React.Fragment>.

Q: When should you use Fragment?

  • When you need to return multiple elements from a component without a wrapper.

Q: What’s the difference between Fragment and div?

  • Fragment doesn’t create a DOM node, while div creates an extra wrapper element.

Q: Can you use keys with Fragment?

  • Yes, but only with the full <React.Fragment> syntax, not the shorthand <>.

Q: What are the benefits of using Fragment?

  • Cleaner DOM structure, better performance, and more semantic HTML.

Q: When should you use div instead of Fragment?

  • When you need styling, event handling, or refs on the wrapper element.

Q: Can you nest Fragments?

  • Yes, you can nest Fragments, but it’s usually unnecessary.

Q: How does Fragment affect performance?

  • Fragment reduces DOM complexity by eliminating unnecessary wrapper nodes.

Q: What’s the difference between Fragment and array return?

  • Fragment is more readable and doesn’t require keys for static content.

Summary

  • React Fragment allows grouping multiple elements without extra DOM nodes
  • Shorthand syntax <> is preferred for simple cases
  • Full syntax <React.Fragment> is needed when keys are required
  • Common use cases include conditional rendering, lists, and form layouts
  • Performance benefit comes from reducing DOM complexity
  • Best practices include using semantic HTML when appropriate
  • Keys are only available with the full Fragment syntax
  • Understanding Fragment is crucial for writing clean, efficient React components

Interview angle 3

  • “Why do fragments exist?” - a component must return one node, and a wrapper div breaks layouts that depend on direct parent-child relationships - flex and grid containers, tables, lists. Fragments group without emitting DOM.
  • “When can’t you use the <> shorthand?” - when you need a key, which is the case whenever you map to fragments. Write <React.Fragment key={id}>.
  • “Do fragments cost anything?” - a node in the React tree, nothing in the DOM. Fewer DOM nodes is a real win in large lists and tables.