frontend / react / element_vs_component.md

React Elements vs Components

3 interview angles 7 min read source

React Elements vs Components

Understanding the distinction between React elements and components is fundamental to React development. While they are related, they serve different purposes and have different characteristics.

Table of Contents


What are React Elements?

React elements are the smallest building blocks of React applications. They are plain objects that describe what you want to see on the screen.

Characteristics of React Elements:

  • Immutable: Once created, they cannot be changed
  • Lightweight: Simple JavaScript objects
  • Platform-agnostic: Can represent DOM elements, native components, or custom components
  • Serializable: Can be converted to JSON

Element Structure:

// React element object structure
const element = {
  type: 'div',
  props: {
    className: 'container',
    children: 'Hello, World!'
  }
};

Creating Elements:

// Using React.createElement
const element = React.createElement(
  'div',
  { className: 'container' },
  'Hello, World!'
);

// Using JSX (compiled to React.createElement)
const element = <div className="container">Hello, World!</div>;

What are React Components?

React components are functions or classes that return React elements. They are reusable pieces of UI that can accept inputs (props) and maintain internal state.

Characteristics of React Components:

  • Reusable: Can be used multiple times with different props
  • Stateful: Can maintain internal state
  • Composable: Can contain other components
  • Lifecycle: Have lifecycle methods (class components) or effects (functional components)

Component Types:

Functional Components:

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

// Arrow function component
const Welcome = (props) => {
  return <h1>Hello, {props.name}!</h1>;
};

// With destructuring
const Welcome = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

Class Components:

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

Key Differences

Aspect React Elements React Components
Type Plain JavaScript objects Functions or classes
Mutability Immutable Mutable (can change state)
Reusability Not reusable Highly reusable
State No internal state Can have internal state
Props Direct properties Accept props as parameters
Lifecycle No lifecycle Have lifecycle methods/effects
Complexity Simple objects Can be complex with logic
Creation React.createElement() or JSX Function/class definitions

Element Example:

// This is a React element
const element = <div className="container">Hello World</div>;

// It's immutable - you can't change it after creation
// element.props.className = 'new-class'; // This won't work

Component Example:

// This is a React component
function Greeting({ name, isLoggedIn }) {
  // Can have logic
  const message = isLoggedIn ? `Welcome back, ${name}!` : 'Please log in.';

  // Can have state (in functional components with hooks)
  const [count, setCount] = useState(0);

  // Returns a React element
  return (
    <div className="greeting">
      <h1>{message}</h1>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

Usage Examples

Elements in Practice:

// Creating elements directly
const headerElement = React.createElement(
  'header',
  { className: 'app-header' },
  React.createElement('h1', null, 'My App'),
  React.createElement('nav', null, 'Navigation')
);

// Using JSX for elements
const buttonElement = (
  <button className="btn btn-primary" onClick={() => alert('Clicked!')}>
    Click Me
  </button>
);

// Rendering elements
ReactDOM.render(buttonElement, document.getElementById('root'));

Components in Practice:

// Functional component
function UserCard({ user }) {
  return (
    <div className="user-card">
      <img src={user.avatar} alt={user.name} />
      <h3>{user.name}</h3>
      <p>{user.email}</p>
    </div>
  );
}

// Using the component
const user = { name: 'John Doe', email: 'john@example.com', avatar: 'avatar.jpg' };
const userCardElement = <UserCard user={user} />;

// Rendering the component
ReactDOM.render(userCardElement, document.getElementById('root'));

Nesting Components:

// Parent component
function App() {
  return (
    <div className="app">
      <Header />
      <MainContent />
      <Footer />
    </div>
  );
}

// Child components
function Header() {
  return <header className="header">Header</header>;
}

function MainContent() {
  return <main className="main">Main Content</main>;
}

function Footer() {
  return <footer className="footer">Footer</footer>;
}

JSX and Elements

JSX Compilation:

// JSX code
const element = (
  <div className="container">
    <h1>Hello World</h1>
    <p>This is JSX</p>
  </div>
);

// Gets compiled to:
const element = React.createElement(
  'div',
  { className: 'container' },
  React.createElement('h1', null, 'Hello World'),
  React.createElement('p', null, 'This is JSX')
);

JSX with Components:

// JSX with custom component
const element = <Welcome name="John" />;

// Gets compiled to:
const element = React.createElement(Welcome, { name: 'John' });

Conditional Rendering:

// Conditional elements
function ConditionalRender({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h1>Welcome back!</h1>; // Returns a React element
  } else {
    return <h1>Please log in.</h1>; // Returns a React element
  }
}

// Conditional rendering with ternary
function Greeting({ isLoggedIn, name }) {
  return (
    <div>
      {isLoggedIn ? (
        <h1>Welcome back, {name}!</h1>
      ) : (
        <h1>Please log in.</h1>
      )}
    </div>
  );
}

Best Practices

1. Use Components for Reusable Logic:

// Good: Component for reusable UI
function Button({ children, onClick, variant = 'primary' }) {
  return (
    <button
      className={`btn btn-${variant}`}
      onClick={onClick}
    >
      {children}
    </button>
  );
}

// Usage
<Button onClick={handleClick}>Click Me</Button>
<Button variant="secondary" onClick={handleCancel}>Cancel</Button>

2. Keep Elements Simple:

// Good: Simple elements for one-off use
const loadingElement = <div className="loading">Loading...</div>;

// Good: Component for complex, reusable logic
function LoadingSpinner({ size = 'medium' }) {
  return (
    <div className={`loading-spinner loading-spinner--${size}`}>
      <div className="spinner"></div>
      <p>Loading...</p>
    </div>
  );
}

3. Use Elements for Static Content:

// Good: Elements for static content
const staticHeader = (
  <header className="static-header">
    <h1>Company Name</h1>
    <p>Tagline</p>
  </header>
);

// Good: Components for dynamic content
function DynamicHeader({ title, subtitle }) {
  return (
    <header className="dynamic-header">
      <h1>{title}</h1>
      <p>{subtitle}</p>
    </header>
  );
}

4. Proper Component Structure:

// Good: Component that returns elements
function UserList({ users }) {
  return (
    <div className="user-list">
      {users.map(user => (
        <UserCard key={user.id} user={user} />
      ))}
    </div>
  );
}

// Good: Element for simple rendering
const emptyState = (
  <div className="empty-state">
    <p>No users found</p>
  </div>
);

Common Interview Questions

Q: What is the difference between a React element and a React component?

  • React elements are plain objects that describe what to render, while React components are functions or classes that return React elements and can have state and lifecycle.

Q: Are React elements mutable?

  • No, React elements are immutable. Once created, they cannot be changed. To update the UI, you create new elements.

Q: How does JSX relate to React elements?

  • JSX is syntactic sugar that gets compiled to React.createElement() calls, which create React elements.

Q: Can you have state in a React element?

  • No, React elements are plain objects and cannot have state. Only React components can have state.

Q: What does a React component return?

  • A React component returns React elements (or null). These elements can be simple DOM elements or other components.

Q: How do you create React elements without JSX?

  • Using React.createElement(type, props, ...children) function.

Q: What is the relationship between components and elements?

  • Components are functions/classes that return elements. Elements are what actually get rendered to the DOM.

Q: Can you pass props to React elements?

  • Yes, props are passed as the second argument to React.createElement() and become the props property of the element object.

Summary

  • React Elements are immutable, lightweight objects that describe what to render
  • React Components are functions or classes that return React elements and can have state and lifecycle
  • Elements are created using React.createElement() or JSX syntax
  • Components are reusable, can accept props, and can maintain internal state
  • JSX gets compiled to React.createElement() calls, creating React elements
  • Use elements for simple, static content; use components for reusable, dynamic UI
  • Understanding this distinction is crucial for effective React development

Interview angle

  • “Element or component?” - a component is a function; an element is the plain object it returns describing what to render. <Foo /> creates an element; Foo is the component. Elements are immutable descriptions, not DOM nodes and not instances.
  • “Why does that distinction matter in practice?” - because creating an element is cheap and does nothing. Passing <Foo /> as a prop is fine; React decides when and whether to call Foo. It also explains why you pass Foo (not <Foo />) where a component type is expected.
  • “Why does defining a component inside another component remount it?” - each render creates a new function identity, so reconciliation sees a different element type and tears down the subtree, losing its state. Define components at module level.