ReactJs JSX

JSX (JavaScript XML) is a syntax extension for JavaScript that allows developers to write HTML-like code within JavaScript. It was created specifically for React to provide a more intuitive way to describe UI structures. While JSX resembles HTML, it compiles down to regular JavaScript function calls and objects.

What is JSX?

JSX is not a template language; it is a syntactic sugar for React.createElement() calls. When you write JSX, a transpiler like Babel converts it to standard JavaScript that browsers can understand:

// JSX syntax
const element = <h1>Hello, world!</h1>;

// Compiles to
const element = React.createElement('h1', null, 'Hello, world!');

This transformation happens at build time, meaning the browser never sees JSX directly. The compiled JavaScript creates a lightweight description of what the UI should look like.

How React Uses JSX

React uses JSX to build an internal tree of elements called the Virtual DOM. This tree representation allows React to efficiently compare versions of the UI and calculate minimal updates needed for the actual DOM:

  1. JSX is written - Developer describes the desired UI state
  2. JSX compiles to JavaScript - Build tools convert JSX to React.createElement() calls
  3. Virtual DOM tree is created - React builds an in-memory representation of the UI
  4. Comparison occurs - React compares the new tree with the previous version
  5. Minimal updates applied - Only changed elements are updated in the actual DOM

This process, known as reconciliation, is what makes React performant even with complex UIs.

JSX Syntax and Rules

JSX follows specific rules that differ slightly from HTML:

JavaScript Expressions in JSX

Embed JavaScript expressions within curly braces:

function Greeting({ name, age }) {
  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>You are {age} years old.</p>
      <p>Next year you'll be {age + 1}.</p>
    </div>
  );
}

JSX Attributes

Use camelCase for attribute names (except data-* and aria-* attributes):

<div className="container" onClick={handleClick} tabIndex={0}>
  <input type="text" value={text} onChange={handleChange} />
</div>

Note that class becomes className and for becomes htmlFor to avoid conflicts with JavaScript reserved words.

Self-Closing Tags

Elements without children must be self-closed:

<img src="photo.jpg" alt="Photo" />
<input type="text" />
<br />

The Children Prop

The children prop is a powerful feature in React that enables flexible component composition. It represents the content between the opening and closing tags of a component.

Basic Children Usage

function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

function App() {
  return (
    <Card>
      <h2>Card Title</h2>
      <p>Card content goes here.</p>
    </Card>
  );
}

Containment Pattern

The containment pattern uses children to create components that don’t know their content ahead of time. This allows maximum flexibility:

function Sidebar({ children }) {
  return (
    <aside className="sidebar">
      {children}
    </aside>
  );
}

function Layout({ children }) {
  return (
    <div className="layout">
      <Sidebar>
        <nav>Navigation items</nav>
      </Sidebar>
      <main>{children}</main>
    </div>
  );
}

Specialization Pattern

Specialization creates specific instances of generic components by providing specific children or props:

function Dialog({ title, children }) {
  return (
    <div className="dialog">
      <h2>{title}</h2>
      <div>{children}</div>
    </div>
  );
}

function WelcomeDialog() {
  return (
    <Dialog title="Welcome">
      <p>Thank you for visiting our application!</p>
    </Dialog>
  );
}

function ConfirmDialog() {
  return (
    <Dialog title="Confirm">
      <p>Are you sure you want to proceed?</p>
      <button>Yes</button>
      <button>No</button>
    </Dialog>
  );
}

Types of Children

The children prop can contain various types of content:

function Wrapper({ children }) {
  return <div>{children}</div>;
}

// String children
<Wrapper>Hello World</Wrapper>

// Element children
<Wrapper><p>Paragraph</p></Wrapper>

// Multiple children
<Wrapper>
  <h1>Title</h1>
  <p>Content</p>
</Wrapper>

// Array of children
<Wrapper>
  {items.map(item => <Item key={item.id} {...item} />)}
</Wrapper>

// Function as children (render props pattern)
<Wrapper>
  {(data) => <div>{data}</div>}
</Wrapper>

Spread Operator in JSX

The JavaScript spread operator (...) can pass all properties of an object as props:

function Button({ variant, size, children, ...rest }) {
  return (
    <button 
      className={`btn btn-${variant} btn-${size}`}
      {...rest}
    >
      {children}
    </button>
  );
}

// Usage
const buttonProps = {
  onClick: handleClick,
  disabled: false,
  'aria-label': 'Submit form'
};

<Button variant="primary" size="large" {...buttonProps}>
  Submit
</Button>

Important: The spread operator must be placed last if you want to override specific props, as the order matters in JSX attributes.

Advanced Component Patterns

Higher-Order Components (HoC)

Higher-Order Components are functions that take a component and return an enhanced version. They encapsulate logic that can be shared across multiple components:

function withMousePosition(Component) {
  return function WrappedComponent(props) {
    const [position, setPosition] = useState({ x: 0, y: 0 });
    
    useEffect(() => {
      const handleMove = (e) => {
        setPosition({ x: e.clientX, y: e.clientY });
      };
      
      window.addEventListener('mousemove', handleMove);
      return () => window.removeEventListener('mousemove', handleMove);
    }, []);
    
    return <Component {...props} mousePosition={position} />;
  };
}

// Usage
const ComponentWithMouse = withMousePosition(MyComponent);

The naming convention for HoCs uses the with prefix (e.g., withAuth, withTheme, withRouter). HoCs should not mutate the original component but rather enhance it through composition.

Render Props

The render props pattern uses a prop (commonly named render) that is a callback function determining what to render:

function DataProvider({ render, url }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(json => {
        setData(json);
        setLoading(false);
      });
  }, [url]);
  
  return render({ data, loading });
}

// Usage
<DataProvider 
  url="/api/users"
  render={({ data, loading }) => (
    loading ? <Spinner /> : <UserList users={data} />
  )}
/>

While render props remain a valid pattern, custom Hooks have largely replaced this approach in modern React development, offering similar functionality with cleaner syntax.

Compound Components

Compound components work together as a cohesive API, sharing implicit state. Kent C. Dodds provides an excellent guide in React Hooks: Compound Components.

function Select({ children }) {
  const [value, setValue] = useState('');
  
  return (
    <SelectContext.Provider value=>
      <select value={value} onChange={(e) => setValue(e.target.value)}>
        {children}
      </select>
    </SelectContext.Provider>
  );
}

function Option({ value, children }) {
  return <option value={value}>{children}</option>;
}

// Usage
<Select>
  <Option value="1">Option 1</Option>
  <Option value="2">Option 2</Option>
</Select>

Resources