Index
  • Components
    • Functional Components
    • Class Components
    • Higher Order Components
  • State
    • useState
    • Component State
    • Redux
  • Props
    • Passing Props
    • Default Props
  • JSX
    • JSX Expressions
    • JSX Elements
    • JSX Children
  • Event Handling
    • Handling User Events
    • Event Pooling
    • Custom Events

Welcome to the first part of a comprehensive guide on React, a popular JavaScript library for building user interfaces. This series is divided into three parts, with each part focusing on different aspects of React. In this part, we'll cover React Components, States, Props, JSX, Event Handling, and Hooks. I aim to explain these concepts in a simple, digestible manner, enabling you to grasp the fundamentals of React quickly and effectively.

React Components:

In the world of React, components are the fundamental building blocks of your application's user interface (UI). They are self-contained, reusable pieces of code that dictate how a certain part of your UI should appear and behave. Three types of components:

Functional Components:

  • Simple JavaScript functions that accept props and return a React element.
  • Stateless and do not have access to lifecycle methods.
  • Ideal for presenting static data and is more efficient.
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Class Components:

  • ES6 classes that extend from React.Component.
  • Have access to local state and lifecycle hooks.
  • Better suited for dynamic data and handling user interactions.
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Higher Order Components (HOCs):

  • A pattern for reusing component logic.
  • Functions that take a component and return a new component.
  • Useful for sharing behavior between components.
function withSubscription(WrappedComponent) {
  return class extends React.Component {
    render() {
      return <WrappedComponent {...this.props} />;
    }
  };
}

State in React

State in React is a built-in object that stores component's properties that can change over time.

  • State is dynamic, and each component can maintain its own state.
  • Changes to a component's state trigger a re-render of that component.
  • There are several ways to handle state in React: useState hook, component state, and Redux.

useState Hook

The useState hook is a function introduced in React 16.8 that lets you add state to your functional components.

  • It takes the initial state as an argument and returns an array of two elements: the current state and a function to update it.
  • The state here doesn’t have to be an object — although it can be if you want. It can be any type you want.
import React, { useState } from 'react';
function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Click me</button>;
}

Component State

Class components have a more traditional way to handle the state.

  • The state is a property of the component class and can be accessed via this.state.
  • To update the state, you have to use the this.setState() method.
class Counter extends React.Component {
  state = {count: 0};
  render() {
    return <button onClick={() => this.setState({ count: this.state.count + 1 })}>Click me</button>;
  }
}

Redux

Redux is a third-party library that provides a predictable state container for JavaScript apps.

  • It helps you manage global state – which is needed across many parts of your application.
  • The state is stored in a single central location, a store, and changes to the state are made using actions and reducers.
import { createStore } from 'redux';
function counter(state = 0, action) {
  return action.type === 'INCREMENT' ? state + 1 : state;
}
let store = createStore(counter);
store.dispatch({ type: 'INCREMENT' });

There are a few more concepts related to the state in React that you should be aware of:

  1. Immutable State: In React, it's important to remember that state should be treated as immutable. This means that instead of modifying state directly, you should always use setState or useState to return a new version of state.
  2. State Propagation: State can be passed down from parent components to child components through props. This is often referred to as "prop drilling". However, excessive prop drilling can lead to unmanageable code, which is where context or state management libraries like Redux come in.
  3. Context API: Introduced in React 16.3, the Context API provides a way to share values between components without having to explicitly pass a prop through every level of the tree. It's useful for sharing stateful values globally across your app, it’s an alternative to Redux.
  4. Reducer Hook (useReducer): For more complex state logic, useReducer is often preferred over useState. It's more suited for handling state objects that contain multiple sub-values.
  5. Custom Hooks: You can create your own Hooks to reuse stateful behavior between different components. Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature.
  6. Component Lifecycle: Understanding when and how state updates in relation to the component lifecycle is crucial. This includes knowing when state updates will trigger re-renders, and how to optimize performance to avoid unnecessary updates.

Props in React

Props (short for properties) in React are used to pass data and event handlers down to child components. They are read-only and help to make components more dynamic and reusable. There are two main ways to handle props in React: passing props and default props.

Passing Props

Passing props is a way of transferring data and functions from a parent component to a child component in React. The child component can then use these props to render dynamic data or to call functions that are defined in the parent component.

Here's a simple example of passing props from a parent component to a child component:

function ParentComponent() {
  const name = 'React Learner';
  return <ChildComponent name={name} />;
}

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

Default Props

Default props in React allow you to set default values for props in a component. They are used when no value or undefined is passed for a prop from a parent component. This is a useful feature when you want to ensure that your component has a certain prop even if no value for it is provided.

Here's an example of how to set default props in a component:

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

Greeting.defaultProps = {
  name: 'Stranger'
};

JSX

JSX stands for JavaScript XML. It is a syntax extension for JavaScript, recommended by React for describing the structure of the user interface.

JSX Expressions

JSX expressions are JavaScript expressions embedded in HTML. They are wrapped in curly braces {}.

const name = 'React Learner';
const element = <h1>Hello, {name}</h1>;

JSX Elements

A JSX element is a representation of a DOM element. It describes what should be rendered on the screen. JSX elements are similar to HTML elements but they can represent JavaScript components as well.

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

JSX Children

JSX tags can contain children, just like HTML tags. This is useful when you want to nest components and HTML elements.

Also, the following points you need to know about JSX:

  1. JSX Prevents Injection Attacks: JSX escapes content before rendering, enhancing security.
  2. JSX Represents Objects: JSX transpiles to React.createElement() calls, creating JavaScript objects.
  3. JSX Must Have One Parent Element: A JSX expression must be wrapped in a single parent element.
  4. JSX Can Contain JavaScript Expressions: You can embed JavaScript expressions in JSX using {}.
  5. JSX Can Be Self-Closing: JSX tags without children can be self-closed using />.
  6. JSX Can Have Comments: Comments in JSX are wrapped in {} and use the /* ... */ syntax.
  7. JSX Can Use JavaScript Variables As Attributes: You can use JavaScript variables as attributes in JSX tags with {}.
  8. JSX Can Conditionally Render Elements: JSX elements can be conditionally rendered using JavaScript logic.

Event Handling

One fundamental aspect of creating interactive web applications is handling events. Let’s break it down:

  1. Adding Event Handlers:
    • Define a function to handle events (e.g., button clicks).
    • Attach the function to the relevant JSX element using onClick.
export default function Button() {
  function handleClick() { //Define a Function
    alert('You clicked me!');
  }
  return (
    <button onClick={handleClick}>Click me</button> //Pass the Function as a Prop
  );
}

2. Inline Event Handlers

Alternatively, you can define event handlers inline within the JSX itself. Here are a few ways to do it:

<button onClick={() => alert('You clicked me!')}>Click me</button> //Using an anonymous function:
<button onClick={() => handleClick()}>Click me</button> //Using an arrow function

💡 Functions passed to event handlers must be passed, not called. Avoid accidentally invoking the function during rendering.

3. Event pooling

  • React optimizes performance by reusing the same event object for multiple handlers.
  • Use event.persist() to avoid issues with asynchronous access to event properties.

4. Custom Events

While React provides built-in events like onClick, you can also create custom events for more specific use cases. To do this, use the CustomEvent constructor or a state management library like Redux.

Hooks

Hooks are a new addition in React 16.8 that lets you use state and other React features without writing a class. Here are some commonly used hooks:

First, let’s understand each hook use cases:

  1. useState: Managing local state.
    • It's used to declare a state variable in a functional component. It returns an array with two items: the current state and a function to update it.
  2. useEffect: Side effects handling.
    • It's used to perform side effects (like data fetching, subscriptions, etc.) in functional components. It's similar to componentDidMount, componentDidUpdate, and componentWillUnmount in class components.
  3. useContext: Context API consumption.
    • It's used to access the value of a context without wrapping a component in a Context.Consumer. It makes the code cleaner and easier to understand.
  4. useReducer: Complex state management.
    • It's used for state management in more complex scenarios. It's similar to how Redux works.
  5. useRef: Referencing DOM nodes.
    • It's used to create a reference to a DOM element or an instance of a component in a functional component.
  6. useCallback: Memoizing functions.
    • It's used to memoize a function, which means it will only recompute the function if the dependencies have changed.
  7. useMemo: Optimizing computations.
    • It's used to memoize expensive computations. It will only recompute the memoized value when one of the dependencies has changed.
  8. useImperativeHandle: Customizing refs.
    • It's used to customize the instance value that is exposed to parent components when using ref.
  9. useLayoutEffect: Synchronous layout effects.
    • It's used to read layout from the DOM and synchronously re-render. It fires after all DOM mutations.
  10. useDebugValue: Debugging custom hooks.
    • It's used to display a label for custom hooks in React DevTools.

So, while Hooks do provide a way to handle state in functional components, they also provide ways to handle lifecycle events, context, and other aspects of React. Will write a separate article only on React Hooks, Stay tuned.

We hope this first part of our React guide provides a solid foundation for understanding the core concepts of React. By grasping these fundamentals, you'll be well-prepared to tackle more advanced topics in the subsequent parts of this series. Remember, learning React is a marathon, not a sprint. Happy coding, and stay tuned for Part 2!