Core Concepts of React

Introduction

React is one of the most popular JavaScript libraries for building user interfaces. Developed and maintained by Facebook (now Meta) along with a strong open-source community, React has revolutionized the way developers think about building web applications. Its component-driven architecture, virtual DOM implementation, declarative style, and support for reusable code make it one of the most efficient and developer-friendly tools in modern front-end development.

In this post, we will introduce the core concepts of React. These concepts form the backbone of React applications and understanding them is crucial before moving toward advanced features. The main topics include JSX, components, props, state, component lifecycle, and rendering logic.

This post will serve as a foundational guide that sets the stage for diving deeper into React development in subsequent posts.


Why Learn React?

Before diving into the core concepts, it is important to understand why React has become so dominant in front-end development. Some reasons include:

  1. Component-Based Architecture – Applications are broken into small, reusable units called components.
  2. Declarative Programming – React makes it easy to describe what the UI should look like at any point in time.
  3. Virtual DOM – Efficiently updates and renders UI elements by minimizing real DOM operations.
  4. Strong Ecosystem – Huge support community, libraries, and tools.
  5. Cross-Platform Development – Can be used for both web (React.js) and mobile apps (React Native).

Core Concepts of React

React applications are built around a handful of fundamental concepts. Let’s introduce each of them briefly before we dive into details.

  1. JSX Syntax and Rules – A syntax extension for JavaScript that allows writing HTML-like code inside JavaScript.
  2. Components (Functional and Class) – Building blocks of a React app.
  3. Props – Mechanism for passing data to components.
  4. State – Internal data management system inside components.
  5. Component Lifecycle – How class components behave over their life span.
  6. Rendering Logic – How React decides what and when to render.

JSX – JavaScript XML

One of the first things developers encounter when learning React is JSX. JSX allows developers to write UI markup directly within JavaScript code. Although JSX looks like HTML, it compiles down to JavaScript function calls.

Example of JSX

const element = <h1>Hello, React!</h1>;

Here, <h1>Hello, React!</h1> is JSX. During the build process, Babel transpiles it into:

const element = React.createElement('h1', null, 'Hello, React!');

Why JSX is Important

  • It allows combining UI structure with JavaScript logic.
  • It improves readability and developer productivity.
  • It helps catch errors at compile time.

Components in React

Components are the building blocks of a React application. Everything in React revolves around components. A component is a reusable piece of UI that can manage its own structure, logic, and style.

React supports two main types of components:

  1. Functional Components
  2. Class Components

Functional Components

Functional components are JavaScript functions that return JSX. They are simple and preferred in modern React development, especially after the introduction of Hooks.

Example of a Functional Component

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

Here, Welcome is a functional component that accepts props and returns JSX.


Class Components

Class components were more common before React Hooks were introduced. They are ES6 classes that extend React.Component and contain methods such as render().

Example of a Class Component

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

While class components are still used, functional components with Hooks are now considered the best practice.


Props in React

Props (short for properties) are a way to pass data from a parent component to a child component. They are immutable, meaning a child cannot modify the props it receives.

Example: Passing Props

function Greeting(props) {
  return <h1>Good Morning, {props.name}</h1>;
}

function App() {
  return (
&lt;div&gt;
  &lt;Greeting name="John" /&gt;
  &lt;Greeting name="Alice" /&gt;
&lt;/div&gt;
); }

Output:

Good Morning, John
Good Morning, Alice

This shows how components become reusable by simply changing the props.


State in React

Unlike props, which are read-only and passed from parent to child, state is local to a component and can change over time. State is used to manage data that changes based on user interaction, API responses, or other events.

State in a Functional Component (using Hooks)

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
&lt;div&gt;
  &lt;p&gt;You clicked {count} times.&lt;/p&gt;
  &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Click Me&lt;/button&gt;
&lt;/div&gt;
); }

Here, useState is a Hook that provides state management inside a functional component.

State in a Class Component

class Counter extends React.Component {
  constructor(props) {
super(props);
this.state = { count: 0 };
} render() {
return (
  &lt;div&gt;
    &lt;p&gt;You clicked {this.state.count} times.&lt;/p&gt;
    &lt;button onClick={() =&gt; this.setState({ count: this.state.count + 1 })}&gt;
      Click Me
    &lt;/button&gt;
  &lt;/div&gt;
);
} }

Component Lifecycle

Every React component goes through a lifecycle, especially class components. The lifecycle includes three main phases:

  1. Mounting – When the component is created and inserted into the DOM.
  2. Updating – When state or props change, and the component re-renders.
  3. Unmounting – When the component is removed from the DOM.

Lifecycle Methods

  • componentDidMount() – Runs after the component is inserted into the DOM.
  • componentDidUpdate() – Runs after props or state change.
  • componentWillUnmount() – Runs before the component is removed.

Example:

class LifecycleDemo extends React.Component {
  componentDidMount() {
console.log("Component mounted!");
} componentDidUpdate() {
console.log("Component updated!");
} componentWillUnmount() {
console.log("Component will unmount!");
} render() {
return &lt;h1&gt;Hello Lifecycle&lt;/h1&gt;;
} }

Rendering Logic

Rendering is at the heart of React. The UI is updated whenever state or props change. React uses a virtual DOM to optimize rendering.

Conditional Rendering

function UserGreeting(props) {
  return <h1>Welcome Back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please Sign Up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
return &lt;UserGreeting /&gt;;
} return <GuestGreeting />; }

Rendering Lists

function List() {
  const items = ['Apple', 'Banana', 'Cherry'];
  return (
&lt;ul&gt;
  {items.map((item, index) =&gt; (
    &lt;li key={index}&gt;{item}&lt;/li&gt;
  ))}
&lt;/ul&gt;
); }

Here, React requires a key prop to uniquely identify elements in a list.


Virtual DOM Explained

The virtual DOM is a lightweight JavaScript object representation of the real DOM. When state or props change, React updates the virtual DOM first, compares it with the previous version (diffing), and then efficiently updates only the changed elements in the real DOM.

This makes React much faster compared to directly manipulating the DOM.


Best Practices for Core Concepts

  1. Use functional components with Hooks instead of class components.
  2. Keep components small and reusable.
  3. Use props for passing data and state for managing local changes.
  4. Always provide unique keys for lists.
  5. Use lifecycle methods or Hooks (like useEffect) for side effects.

Real-World Example – Simple Todo App

Let’s combine the above concepts into a small example.

import React, { useState } from 'react';

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');

  const addTodo = () => {
if (input.trim() !== '') {
  setTodos(&#91;...todos, input]);
  setInput('');
}
}; return (
&lt;div&gt;
  &lt;h1&gt;Todo List&lt;/h1&gt;
  &lt;input
    type="text"
    value={input}
    onChange={(e) =&gt; setInput(e.target.value)}
  /&gt;
  &lt;button onClick={addTodo}&gt;Add&lt;/button&gt;
  &lt;ul&gt;
    {todos.map((todo, index) =&gt; (
      &lt;li key={index}&gt;{todo}&lt;/li&gt;
    ))}
  &lt;/ul&gt;
&lt;/div&gt;
); } export default TodoApp;

This example demonstrates:

  • Using state (useState)
  • Handling input changes
  • Rendering lists with keys
  • Component structure and JSX


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *