# React Basics: How Components, JSX, and React.createElement Really Work

* * *

## Table of Contents

1.  The File Structure We're Working With
    
2.  What is a Component? (Function as a Component)
    
3.  Fragments — What They Are and What Happens Without Them
    
4.  Can You Write Components Inside main.jsx?
    
5.  Using Variables Inside JSX
    
6.  How JSX Actually Works — The React.createElement Story
    
7.  The Plain JavaScript Object Approach (No JSX)
    
8.  Passing Multiple Children to React.createElement
    
9.  Vite React vs Create React App — Key Differences
    
10.  Summary Cheatsheet
     

* * *

## 1\. The File Structure We're Working With

Before I explain anything, let me show you the three files we are dealing with and what job each one does.

```plaintext
src/
├── main.jsx      ← Entry point. This is where React starts.
├── App.jsx       ← Root component. The parent of all components.
└── Chai.jsx      ← A child component. Imported and used inside App.
```

Think of it like a tree:

```plaintext
main.jsx
  └── App
        └── Chai
```

`main.jsx` is the one that talks to the browser's actual DOM. `App` is your top-level React component. `Chai` is a smaller piece that `App` uses.

* * *

## 2\. What is a Component? (Function as a Component)

In React, a **component is simply a JavaScript function that returns JSX (HTML-like code)**.

Here is `Chai.jsx`:

```jsx
function Chai() {
  return (
    <h2>chai in react</h2>
  );
}

export default Chai;
```

And here is `App.jsx` importing and using it:

```jsx
import Chai from "./Chai";

function App() {
  return (
    <>
      <Chai />
    </>
  );
}

export default App;
```

**Rules you must follow when writing a component:**

*   The function name **must start with a capital letter**. `Chai` is valid. `chai` is not — React will treat it as a plain HTML tag.
    
*   The function **must return JSX** (or `null`).
    
*   You use it like an HTML tag: `<Chai />` — self-closing is fine when there's no children.
    

* * *

## 3\. Fragments — What They Are and What Happens Without Them

### What is a Fragment?

A Fragment (`<>...</>`) is an invisible wrapper. It lets you return multiple elements from a component **without adding an extra DOM node**.

```jsx
function App() {
  return (
    <>
      <Chai />
      <h1>Hello</h1>
    </>
  );
}
```

The `<>` and `</>` are shorthand for `<React.Fragment>` and `</React.Fragment>`.

* * *

### What Happens If You Don't Use a Fragment?

This is one of the most important rules in React:

> **A component can only return ONE root element.**

If you try to return two sibling elements without a wrapper, you get an error.

#### ❌ This Will Crash — No Wrapper

```jsx
function App() {
  return (
    <Chai />
    <h1>Hello</h1>
  );
}
```

**Output / Error:**

```plaintext
SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag.
Did you want a JSX fragment <>...</>?
```

#### ✅ Fix 1 — Use a Fragment (Recommended)

```jsx
function App() {
  return (
    <>
      <Chai />
      <h1>Hello</h1>
    </>
  );
}
```

**DOM Output:**

```html
<h2>chai in react</h2>
<h1>Hello</h1>
```

No extra wrapper `<div>` in the DOM. Clean.

#### ✅ Fix 2 — Wrap in a `<div>` (Adds extra node)

```jsx
function App() {
  return (
    <div>
      <Chai />
      <h1>Hello</h1>
    </div>
  );
}
```

**DOM Output:**

```html
<div>
  <h2>chai in react</h2>
  <h1>Hello</h1>
</div>
```

This works, but you get an extra `<div>` in your HTML. For small projects, it doesn't matter. But when you have deep nesting, it creates "div soup" — too many useless wrappers.

* * *

### Does the Error Differ Between Vite React and Create React App (CRA)?

Yes, slightly. But the **root rule is the same** — one parent element per return.

| Tool | Error Message Style | Error Shown At |
| --- | --- | --- |
| **Vite + React** | Shows in browser overlay (red screen), very clear | Build time + Runtime |
| **Create React App** | Shows in browser console and overlay | Compile time |

#### In Vite React:

Vite uses **esbuild** under the hood. It processes JSX very fast and shows you a clear overlay in the browser with the exact line number.

```plaintext
[plugin:vite:react-babel] Adjacent JSX elements must be wrapped
  in an enclosing tag. (5:4)
```

#### In Create React App (CRA):

CRA uses **Babel** with Webpack. The error looks like this in the terminal and browser:

```plaintext
Failed to compile.
./src/App.js
  Line 5:5: Parsing error: Adjacent JSX elements must be
  wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?
```

**The fix is identical in both.** Use `<>...</>` or a `<div>`.

* * *

## 4\. Can You Write Components Inside main.jsx?

Yes, absolutely. React doesn't care **which file** your component is in. What matters is that it's a valid function returning JSX.

Here's the complete `main.jsx` from your code, and I've shown how you can define `MyApp` right there in the same file:

```jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';

// ✅ You can define a component right here in main.jsx
function MyApp() {
  return (
    <div>
      <h1>Custom App | chai</h1>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
```

**Browser Output:**

```plaintext
chai in react        ← from Chai component inside App
```

> The `MyApp` function is defined but not rendered here because we're rendering `<App />`. If you changed `root.render(<App />)` to `root.render(<MyApp />)`, you'd see "Custom App | chai" instead.

**Why separate files then?**

As your project grows, keeping every component in one file becomes messy. So we split them into their own files — one component per file. But technically, there's nothing stopping you from writing everything in `main.jsx`.

* * *

## 5\. Using Variables Inside JSX

You can embed any JavaScript variable inside JSX using **curly braces** `{}`.

```jsx
function App() {
  const username = "chai aur code";

  return (
    <>
      <Chai />
      <h1>chai aur react {username}</h1>
      <p>test para</p>
    </>
  );
}
```

**Browser Output:**

```plaintext
chai is ready
chai aur react chai aur code
test para
```

The `{username}` gets replaced with the actual value of the variable at render time.

You can put any valid JavaScript expression inside `{}`:

```jsx
<h1>{2 + 2}</h1>           // Output: 4
<h1>{"hello".toUpperCase()}</h1>  // Output: HELLO
<h1>{username}</h1>        // Output: chai aur code
```

* * *

## 6\. How JSX Actually Works — The React.createElement Story

This is the part most beginners skip, but I want you to understand it deeply.

When you write this JSX:

```jsx
function Chai() {
  return (
    <h2>chai in react</h2>
  );
}
```

You think this is HTML. It's not. **JSX is not HTML.** It is syntactic sugar that gets compiled down to plain JavaScript function calls.

Under the hood, Babel (or esbuild in Vite) transforms your JSX into:

```js
function Chai() {
  return React.createElement("h2", null, "chai in react");
}
```

### React.createElement — The Syntax

```js
React.createElement(type, props, ...children)
```

| Argument | What It Is | Example |
| --- | --- | --- |
| `type` | The HTML tag or Component name | `"h2"`, `"a"`, `App` |
| `props` | An object of attributes (like `href`, `className`) | `{ href: "https://..." }` |
| `...children` | Text or other elements inside | `"chai in react"` |

#### Example 1 — A Simple Tag

**JSX you write:**

```jsx
<h2>chai in react</h2>
```

**What it becomes:**

```js
React.createElement("h2", null, "chai in react")
```

*   Type: `"h2"` (string, because it's a native HTML tag)
    
*   Props: `null` (no attributes)
    
*   Children: `"chai in react"` (plain text)
    

**DOM Output:**

```html
<h2>chai in react</h2>
```

* * *

#### Example 2 — A Tag With Attributes

**JSX you write:**

```jsx
<a href="https://google.com" target="_blank">Visit google</a>
```

**What it becomes:**

```js
React.createElement(
  "a",
  { href: "https://google.com", target: "_blank" },
  "Visit google"
)
```

**DOM Output:**

```html
<a href="https://google.com" target="_blank">Visit google</a>
```

* * *

#### Example 3 — A Component (Capital Letter)

**JSX you write:**

```jsx
<Chai />
```

**What it becomes:**

```js
React.createElement(Chai, null)
```

*   Type: `Chai` — the actual function reference, **not a string**.
    
*   Props: `null`
    
*   Children: none
    

React sees a capital letter → it knows this is a component → it calls the `Chai` function → uses what it returns.

* * *

### Where is `React` Imported in Older Code?

In older React (before version 17), you had to import React at the top of every file that used JSX — even if you never used the `React` variable directly:

```js
import React from 'react';
```

This was needed because JSX compiled to `React.createElement(...)`, so React had to be in scope.

From **React 17+**, this is no longer necessary. The new JSX transform handles it automatically. That's why in Vite + React projects you don't always see that import.

* * *

## 7\. The Plain JavaScript Object Approach (No JSX)

In your `main.jsx`, there's a commented-out block:

```js
// const ReactElement = {
//     type: 'a',
//     props: {
//         href: 'https://google.com',
//         target: '_blank'
//     },
//     children: 'Click me to visit google'
// }
```

This is showing you what React elements look like **internally as a plain JavaScript object**. When React processes `React.createElement(...)`, it produces an object that looks roughly like this.

However — and this is important — **you cannot pass this raw object directly to** `root.render()`. React will not know what to do with it. You must use `React.createElement()` or JSX.

The reason this is commented out is to teach you that **React elements are just objects**, not magic. React reads this object tree and figures out what to put in the DOM.

* * *

## 8\. Passing Multiple Children to React.createElement

Here's the most interesting part of your code:

```js
const anotherElement = (
  <a href="https://google.com" target="_blank">Visit google</a>
);

const anotherUser = "chai aur react";

const reactElement = React.createElement(
  'a',
  { href: 'https://google.com', target: '_blank' },
  'click me to visit google',
  anotherElement
);

ReactDOM.createRoot(document.getElementById('root')).render(
  reactElement
);
```

Let me break this down piece by piece.

### Step 1 — `anotherElement` is a JSX variable

```jsx
const anotherElement = (
  <a href="https://google.com" target="_blank">Visit google</a>
);
```

This is valid JSX stored in a variable. It compiles to:

```js
const anotherElement = React.createElement(
  'a',
  { href: "https://google.com", target: "_blank" },
  "Visit google"
);
```

So `anotherElement` is now a React element object.

### Step 2 — `React.createElement` With Multiple Children

```js
const reactElement = React.createElement(
  'a',
  { href: 'https://google.com', target: '_blank' },
  'click me to visit google',  // child 1 — plain text
  anotherElement               // child 2 — another React element
);
```

*   **Type:** `'a'` → an anchor tag
    
*   **Props:** `href` and `target`
    
*   **Child 1:** The text `"click me to visit google"`
    
*   **Child 2:** `anotherElement` — which is another `<a>` tag
    

**DOM Output:**

```html
<a href="https://google.com" target="_blank">
  click me to visit google
  <a href="https://google.com" target="_blank">Visit google</a>
</a>
```

An `<a>` tag inside another `<a>` tag is technically invalid HTML (nested anchors), but this example is purely for learning purposes — to show you that **you can nest elements using** `React.createElement` **by passing them as additional arguments**.

### Step 3 — Rendering

```js
ReactDOM.createRoot(document.getElementById('root')).render(
  reactElement
);
```

`ReactDOM.createRoot()` finds the `<div id="root">` in your `index.html` and React takes over that div, rendering `reactElement` into it.

* * *

## 9\. Vite React vs Create React App — Key Differences

| Feature | Vite + React | Create React App (CRA) |
| --- | --- | --- |
| **Speed** | Very fast (uses esbuild) | Slower (uses Webpack) |
| **Entry file** | `main.jsx` | `index.js` |
| `import React` | Not always needed | Required in older versions |
| `root.render()` **wrapping** | No `<React.StrictMode>` by default | Wraps in `<React.StrictMode>` |
| **JSX transform** | New (automatic) | New since v17 |
| **Fragment requirement** | Same — one root per return | Same — one root per return |

### CRA — Default main.jsx (index.js)

```jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
```

### Vite — Default main.jsx

```jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <App />
);
```

Both use `ReactDOM.createRoot()` — the modern React 18 API. Older CRA projects used `ReactDOM.render()` (deprecated).

* * *

## 10\. Summary Cheatsheet

```plaintext
JSX                           →    React.createElement()
------------------------------------------------------------
<h2>chai</h2>                 →    React.createElement("h2", null, "chai")
<a href="...">text</a>        →    React.createElement("a", {href:"..."}, "text")
<Chai />                      →    React.createElement(Chai, null)
<h1>{username}</h1>           →    React.createElement("h1", null, username)
<><Chai /><h1>hi</h1></>      →    React.createElement(Fragment, null,
                                     React.createElement(Chai, null),
                                     React.createElement("h1", null, "hi"))
```

### Rules to Always Remember

1.  **One root element per return** — use `<>...</>` to wrap multiple elements.
    
2.  **Component names must start with a capital letter** — `Chai`, not `chai`.
    
3.  **JSX is not HTML** — it compiles to `React.createElement()`.
    
4.  **Curly braces** `{}` let you inject JavaScript expressions into JSX.
    
5.  **You can define a component anywhere** — same file, different file, it doesn't matter as long as you import it correctly.
    
6.  `React.createElement(type, props, ...children)` — children can be text, variables, or other React elements.
    
7.  **Fragments add no DOM nodes** — prefer `<>...</>` over wrapping `<div>` unless you need the div.
