https://dev.to/codedthemes/reactjs-cheatsheet-the-ultimate-guide-29gf?ref=dailydev

React Intro

React is a popular JavaScript library for building user interfaces. It allows you to create reusable UI components and efficiently update and render them when the underlying data changes.

Key Features

  • Component-Based Architecture: React follows a component-based approach, allowing you to create self-contained, reusable UI components. These components can be composed together to build complex user interfaces.
  • Virtual DOM: React utilizes a virtual DOM (Document Object Model) for efficient rendering. The virtual DOM is a lightweight copy of the actual DOM, and React uses it to efficiently update and render only the necessary components when the state or props change.
  • Unidirectional Data Flow: React enforces a unidirectional data flow, which means data flows in a single direction. This helps maintain a predictable state management and makes it easier to debug and understand how data changes in your application.
  • JSX Syntax: React introduces JSX (JavaScript XML), a syntax extension that allows you to write HTML-like code within your JavaScript files. JSX provides a declarative way to describe the structure and appearance of your components.

Setting up the Development Environment

To start using React you must make sure you have node installed on your computer

  • ✅ Node

    To check whether node is installed or not use:

    node -v

Creating our react Applicaiton.

There are two ways to create a react Application

  • ➡️ Create React App (CRA)
  • ➡️ Vite

Using Vite

Vite is a build tool that offers a faster and more efficient development experience when working with React (and other frameworks). It is an alternative to tools like Create React App (CRA) and provides several benefits that make it worth considering:

  • 💡 Fast Development Server: Vite utilizes an extremely fast development server that leverages native ES modules in modern browsers. It offers quick startup times and provides near-instant hot module replacement (HMR), allowing you to see your changes immediately without having to manually refresh the page.
  • 💡 Instant Server-Side Rendering (SSR): Vite supports instant server-side rendering for React applications, enabling faster initial page loads and better SEO (Search Engine Optimization) by serving pre-rendered HTML.
  • 💡 Efficient Production Builds: When it comes to production builds, Vite optimizes the output by leveraging native ES modules. It generates highly optimized and tree-shaken bundles, resulting in smaller file sizes and faster load times for your React application.
  • 💡 Native Support for JSX and TypeScript: Vite has built-in support for JSX and TypeScript, allowing you to write React components using JSX syntax and take advantage of TypeScript’s static typing.
  • 💡 Flexible Configuration: Vite provides a simple and intuitive configuration file (vite.config.js) that allows you to customize the build process according to your project’s specific needs. It offers a wide range of options for customization, making it a flexible tool for React development.

    Installing the latest version

npm create vite@latest

For a specific version

npm create vite@4.1.0

Full Process

npm create vite@latest
 
**Choose your application name**
 
Choose the project you want to install
- ➡️ Vanilla
- ➡️ Vue
- ➡️ React
- ➡️ Preact
- ➡️ Lite
- ➡️ Svelt ...
 
**Install Your dependencies**
npm install
or
npm i

Running our development server

To run our development server you simply type

npm run dev

Project Structure

my-react-app/
  ├─ node_modules/
  ├─ public/
  │   ├─ favicon.ico
  │   ├─ index.html
  │   └─ robots.txt
  ├─ src/
  │   ├─ components/
  │   │   └─ App.tsx
  │   ├─ styles/
  │   │   └─ App.css
  │   ├─ index.tsx
  │   └─ index.css
  ├─ .gitignore
  ├─ package.json
  ├─ README.md
  └─ vite.config.ts
 
  • Public assets of our website: Images videos etc…
  • SRC : source code of our applicaiton
    • App.tsx : App.tsx is a TypeScript file that contains a React component.
    • styles/: This folder holds the CSS or styling files for your components. In this example, App.css is a CSS file specific to the App.tsx component.
    • index.tsx: This TypeScript file is the entry point of your React application. It typically renders the main component (in this case, App.tsx) into the DOM. You can import and use other components or libraries in this file.
    • index.css: This CSS file is specific to the index.tsx file and can be used to apply global styles to your application.
  • Index.html : contains a div that is the container of our application (id=root)
  • tsconfig.json
  • vite.config.ts

Creating our first react component.

Creating our component

To create our react component we must put it inside the src folder

Create a message component of the file type tsx

// PascalCasing
// Should always be followed when creating a funciton component.
function Message(){
    //JSX: JavaScript XML, this code will be converted to JS code.
    return <h1>Good Morning</h1>;
}
// Exporting the component so that it can be used in other files.
export default Message;

Using our component

To use our component we simply are gonna register it to our app and use it inside our app.

import Message from "./Message"
 
function App() {
  return (
    <div>
      <Message></Message>
    </div>
  ) /*  or use self closing tag
  return <div><Message/></div>
  */
}
export default App

The Beauty of JSX

// PascalCasing
 
// Should always be followed when creating a funciton component.
 
function Message() {
  const name = "Gisa ilunga Daniel" // inside {} you can write any javascript expression
  // return <h1>Good {name}</h1>;
  // You can use conditional statements
 
  if (name) return <h1>Good {name}</h1>
  return <h1>Good Human.</h1>
}
// Exporting the component so that it can be used in other files.
export default Message

File extention

In TypeScript, there are two main file extensions used:

.ts:
  • 🔖 The .ts extension is used for regular TypeScript files. These files contain TypeScript code, which gets transpiled into JavaScript before being executed. You should use the .ts extension for most of your TypeScript files.
.tsx:
  • 🔖 The .tsx extension is used for TypeScript files that contain JSX (JavaScript XML) syntax. JSX allows you to write HTML-like code within your TypeScript files, making it easier to define React components. When using React with TypeScript, you should use the .tsx extension for files that contain JSX code.

How does React works ?

React and ReactDOM

React and ReactDOM are two key libraries in the React ecosystem:

  1. React: React is a JavaScript library for building user interfaces. It provides a declarative and efficient way to create reusable UI components. React allows you to write components using JSX syntax, which is a combination of JavaScript and XML-like syntax. React focuses on the rendering of components and manages component lifecycle, state, and props. It provides a virtual DOM (Document Object Model) for efficient updates and rendering of components.
  2. ReactDOM: ReactDOM is a package that serves as the glue between React and the actual DOM (Document Object Model) in the browser. It provides methods and APIs to render React components into the browser DOM, handle updates, and interact with the DOM.

React ecosystem

The React ecosystem refers to the collection of libraries, tools, and resources that are built around or are compatible with React. It has grown significantly since React’s initial release and continues to expand, providing developers with a wide range of options and capabilities to enhance their React development experience.

  1. React Router: React Router is a popular library for handling routing in React applications. It allows you to define and manage different routes, enabling navigation between different views or pages within your application.
  2. State Management Libraries: React itself provides local component state management, but for more complex applications, you may need additional state management solutions. Libraries like Redux, MobX, and Zustand offer centralized state management, enabling you to manage application-wide state and simplify data flow within your React components.
  3. React UI Component Libraries: Various UI component libraries provide pre-built and customizable UI components for React applications. Examples include Material-UI, Ant Design, Semantic UI React, and Chakra UI. These libraries help you build consistent and visually appealing user interfaces by offering ready-to-use components like buttons, forms, modals, and more.
  4. React Native: React Native is a framework that allows you to build native mobile applications using React. With React Native, you can write code in React and deploy it to iOS and Android devices, sharing a significant portion of the codebase between platforms.
  5. Next.js: Next.js is a popular framework built on top of React that adds server-side rendering (SSR) capabilities, along with other features like static site generation (SSG), routing, and API handling. It simplifies the creation of server-rendered React applications and offers a seamless developer experience.
  6. Testing Libraries: React has a robust ecosystem of testing libraries and frameworks. Tools like Jest, React Testing Library, Enzyme, and Cypress provide various options for unit testing, integration testing, and end-to-end testing of React applications.
  7. Tooling and Build Systems: Tools like Vite, Create React App (CRA), and webpack provide convenient setups and configurations for building, bundling, and optimizing React applications. They handle transpilation, code splitting, hot module replacement, and other optimizations to improve the development and production workflows.
  8. React DevTools: React DevTools is a browser extension and standalone tool that helps developers inspect, debug, and profile React components in real-time. It provides insights into the component tree, state changes, and performance optimizations.

Library VS Framework

Library:

A tool that provides specific functionalities

A library is a collection of pre-written code that provides specific functionality or features. It typically consists of a set of reusable modules or components that developers can use in their applications. Libraries are designed to be flexible and modular, allowing developers to pick and choose the components they need and integrate them into their own codebase. Examples of libraries include React, Axios, Lodash, and Moment.js.

  • ➡️ Libraries are often focused on solving a particular problem or providing a specific set of functionalities.
  • ➡️ Developers have more control over how they use libraries and can integrate them into their existing codebase as needed.
  • ➡️ Libraries are typically less opinionated and allow for greater flexibility in application architecture and design choices.
  • ➡️ Libraries are usually imported and used within the developer’s code, acting as a tool to extend or enhance existing functionality.

Framework:

A set of tools and guidelines for building apps

A framework, on the other hand, is a more comprehensive software development platform that provides a structured approach to building applications. It usually includes a set of rules, conventions, and tools that guide the development process. Frameworks provide a foundation or scaffolding for building applications by defining the overall architecture, flow control, and common patterns. Examples of frameworks include Angular, React (when used with tools like Next.js or Gatsby), and Ruby on Rails.

  • ➡️ Frameworks often provide a complete solution for developing a specific type of application, offering a defined structure and a set of rules to follow.
  • ➡️ Developers work within the framework’s constraints, adhering to its conventions and patterns.
  • ➡️ Frameworks handle many aspects of the application, such as routing, data management, and building blocks, which can reduce development time.
  • ➡️ Frameworks are typically more opinionated and impose a specific way of doing things to ensure consistency across the application.

Returning multiple elements in React:

In React, there are several ways to return multiple elements from a component. Let’s explore each approach:

Using an Array or Fragment

You can use an array or a React fragment ([...]) to wrap multiple elements and return them together. Here’s an example:

function MyComponent() {
  return [<h1 key="title">Hello</h1>, <p key="description">Welcome to my React component</p>]
}

Using JSX Parentheses

You can enclose multiple elements within JSX parentheses to return them together. Here’s an example:

function MyComponent() {
  return (
    <div>
      <h1>Hello</h1>
      <p>Welcome to my React component</p>
    </div>
  )
}

Using a Parent Container Element

You can wrap multiple elements in a parent container element and return it. Here’s an example:

function MyComponent() {
  return (
    <div>
      <h1>Hello</h1>
      <p>Welcome to my React component</p>
    </div>
  )
}

Using Fragments

React Fragments allow you to return multiple elements without adding an extra wrapper element. Here’s an example:

function MyComponent() {
  return (
    <>
      <h1>Hello</h1>
      <p>Welcome to my React component</p>
    </>
  )
}

Choose the approach that best fits your needs and the specific requirements of your component.

Rendering our components

Using map method to render a list of components

#map In React, the map() method is commonly used to iterate over an array of data and dynamically render components based on that data. The map() method is often used within the JSX code to generate a new array of React components or JSX elements.

function ListGroup() {
  const items = ["Rwanda", "Burunde", "Uganda", "Kenya"]
  return (
    <>
            <h1>THis is just a best way </h1>     {" "}
      <ul className="border inline-block rounded-lg ">
               {" "}
        {items.map((item, index) => (
          <li className="text-gray-900 border p-4 " key={index}>
                        {item}         {" "}
          </li>
        ))}
             {" "}
      </ul>
         {" "}
    </>
  )
}

Conditional Rendering

#conditionals Conditional rendering in React allows you to conditionally display or hide components, elements, or content based on certain conditions or state values. It allows you to dynamically control what gets rendered in the user interface.

There are several ways to achieve conditional rendering in React:

  • ➡️ if/else Statements: You can use traditional JavaScript if/else statements to conditionally render components or elements. Here’s an example:
import React from "react"
 
function MyComponent({ isLoggedIn }) {
  if (isLoggedIn) {
    return <p>Welcome, user!</p>
  } else {
    return <p>Please log in to continue.</p>
  }
}
  • ➡️ Ternary Operator: The ternary operator (condition ? trueValue : falseValue) is a concise way to conditionally render content. Here’s an example:
import React from "react"
 
function MyComponent({ isLoggedIn }) {
  return isLoggedIn ? <p>Welcome, user!</p> : <p>Please log in to continue.</p>
}
  • ➡️ Logical && Operator: The logical AND (&&) operator can be used for simple conditional rendering. If the condition evaluates to true, the subsequent element will be rendered. Otherwise, it will be skipped. Here’s an example:
import React from "react"
function MyComponent({ isLoggedIn }) {
  return isLoggedIn && <p>Welcome, user!</p>
}
  • ➡️ Switch Statement: In more complex scenarios with multiple conditions, you can use a switch statement for conditional rendering. Each case can return the desired component or content. Here’s an example:
import React from "react"
 
function MyComponent({ role }) {
  switch (role) {
    case "admin":
      return <AdminDashboard />
    case "user":
      return <UserDashboard />
    default:
      return <GuestMessage />
  }
}

Conditional Rendering implementation

We want to render some list of items if they are there otherwise render something else

The not so good way, where we have a bit of redundancy

function ListGroup() {
  const items = ["Rwanda", "Burunde", "Uganda", "Kenya"]
  if (items.length === 0)
    return (
      <>
                <h1>Nothing To render in here</h1>        <p>No Item found </p>     {" "}
      </>
    )
  return (
    <>
            <h1>THis is just a best way </h1>     {" "}
      <ul className="inline-block border rounded-lg ">
               {" "}
        {items.map((item, index) => (
          <li className="p-4 text-gray-900 border " key={index}>
                        {item}         {" "}
          </li>
        ))}
             {" "}
      </ul>
         {" "}
    </>
  )
}
export default ListGroup

A better implementation to avoid redundancy

function ListGroup() {
  const items = ["Rwanda", "Burunde", "Uganda", "Kenya"]
  return (
    <>
            <h1>THis is just a best way </h1>           {" "}
      {items.length === 0 ? <p>No Item To render found</p> : null}
      // The above can be rewritten beaurifully like this: // {items.length === 0 && (
        <p>No Item To render found</p>
      )}
      <ul className="inline-block border rounded-lg ">
               {" "}
        {items.map((item, index) => (
          <li className="p-4 text-gray-900 border " key={index}>
                        {item}         {" "}
          </li>
        ))}
             {" "}
      </ul>
         {" "}
    </>
  )
}
export default ListGroup

Sometimes the logic above in the ternary operator can get a bit complicated and it can pollute our jsx markup , in those cases we can always extract the logic and store it in a variable of ra constant .

function ListGroup() {
  const items = ["Rwanda", "Burunde", "Uganda", "Kenya"]
  const message = items.length === 0 ? <p>No Item To render found</p> : null
  return (
    <>
            <h1>THis is just a best way </h1>      {message}     {" "}
      <ul className="inline-block border rounded-lg ">
               {" "}
        {items.map((item, index) => (
          <li className="p-4 text-gray-900 border " key={index}>
                        {item}         {" "}
          </li>
        ))}
             {" "}
      </ul>
         {" "}
    </>
  )
}
export default ListGroup

Now it's much better, we can also move the logic in a function to make our code even cleaner

function ListGroup() {
  const items = ["Rwanda", "Burunde", "Uganda", "Kenya"]
  const getMesssage = () => {
    return items.length === 0 ? <p>No Item To render found</p> : null
  }
  return (
    <>
            <h1>THis is just a best way </h1>      {getMesssage()}     {" "}
      <ul className="inline-block border rounded-lg ">
               {" "}
        {items.map((item, index) => (
          <li className="p-4 text-gray-900 border " key={index}>
                        {item}         {" "}
          </li>
        ))}
             {" "}
      </ul>
         {" "}
    </>
  )
}
export default ListGroup

The advantage of using functions is that functions accepts arguments, perhaps we can get different messages depending on some given parameters.

Handling Events

In React, event handling allows you to respond to user interactions and perform actions based on those events.

Basic Event Handling

To handle events in React, follow these steps:

  • ➡️ Attach an Event Listener:

    • [/] In JSX, attach an event listener by using the on<EventName> attribute on an element. For example, to handle a click event, use onClick.
  • ➡️ Define an Event Handler Function:

    • [/] Create a function that will be called when the event occurs. It can receive an event object as an argument, which contains information about the event.
  • ➡️ Update State or Perform Actions:

    • [/] Inside the event handler function, update component state, call other functions, make API requests, or perform any desired action based on the event.

Here’s an example of handling a click event in a React component:

import React, { useState } from "react"
 
function MyComponent() {
  const [count, setCount] = useState(0)
 
  const handleClick = () => {
    setCount(count + 1)
  }
 
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increment</button>
    </div>
  )
}

Common Event Types

React supports various events that you can handle. Some commonly used events include:

  • 🔥 onClick: Triggered when an element is clicked.
  • 🔥 onChange: Fired when the value of an input element changes.
  • 🔥 onSubmit: Called when a form is submitted.
  • 🔥 onMouseOver/onMouseOut: Invoked when the mouse pointer enters/leaves an element.
  • 🔥 onKeyPress: Triggered when a key is pressed.

Advanced Techniques

As you become more comfortable with event handling in React, you can explore advanced techniques:

Event Object

When an event occurs, React passes an event object to the event handler function. This object contains information about the event, such as the target element, mouse coordinates, or key codes. You can access this information within the event handler function.

function handleClick(event) {
  console.log("Clicked element:", event.target)
}

Passing Arguments to Event Handlers

To pass additional arguments to the event handler function, you can use arrow functions or the bind() method to set the context and arguments explicitly.

<button onClick={() => handleClick(arg1, arg2)}>Click Me</button>
 
<button onClick={handleClick.bind(null, arg1, arg2)}>Click Me</button>

Event Delegation

In some cases, you may want to handle events for multiple elements using a single event handler. This is called event delegation. You can attach the event listener to a parent element and determine the target element within the handler function.

function handleButtonClick(event) {
  if (event.target.tagName === "BUTTON") {
    // Handle button click
  }
}
Further Reading

For more information on event handling in React, refer to the official React documentation: Handling Events

Adding event to our componenets

Adding an event Directly to our element

function ListGroup() {
  const items = ["Rwanda", "Burunde", "Uganda", "Kenya"]
  return (
    <>
            <h1>THis is just a best way </h1>           
      {items.length == 0 && <p>No Items in here</p>}     
      <ul className="inline-block border rounded-lg ">
               {" "}
        {items.map((item, index) => (
          <li className="p-4 text-gray-900 border " key={index} onClick={(e) => console.log(e)}>
                        {item}         {" "}
          </li>
        ))}
             {" "}
      </ul>
         {" "}
    </>
  )
}
export default ListGroup

The Above implementation is great and at first seems not to have any issue, but sometimes you would want to add a more complex event.

Now we have decoupled our codes into a function and the implementation is much better.

import { MouseEvent } from "react"
function ListGroup() {
  const items = ["Rwanda", "Burunde", "Uganda", "Kenya"]
  const handleClick = (e: MouseEvent) => console.log(e)
  return (
    <>
            <h1>THis is just a best way </h1>      {items.length == 0 && <p>No Items in here</p>}   
       {" "}
      <ul className="inline-block border rounded-lg ">
               {" "}
        {items.map((item, index) => (
          <li className="p-4 text-gray-900 border " key={index} onClick={handleClick}>
                        {item}         {" "}
          </li>
        ))}
             {" "}
      </ul>
         {" "}
    </>
  )
}
export default ListGroup

Because we are using type script, we must use type annotation, since we are passing an event listener to our e, then we must reference that .that is why we used :MouseEvent.

React State Hook

USE STATE (useState)

#hook

What is a state in react ?

State in React is a way to manage and store data that can change over time. It allows you to create dynamic and interactive user interfaces. In functional components, you can use the useState hook to add state management to your components.

Using useState hook

Here’s how you can use the useState hook in a React component:

import React, { useState } from "react"
 
function Counter() {
  // Declare a state variable named "count" with an initial value of 0
  const [count, setCount] = useState(0)
 
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  )
}
 
export default Counter

What happened above is that:

  • [p] We import useState from React.
  • [p] Inside the Counter function component, we declare a state variable count using useState(0).
    • 🔖 The useState function takes an initial value (in this case, 0) and returns an array with two elements: the current state value (count) and a function to update it (setCount).
  • [p] We display the current value of count in the JSX using {count}.
  • [p] When the “Increment” button is clicked, we call setCount to update the count state by incrementing it.

Rules for Using useState

  1. [f] You must call useState inside a function component, not within regular JavaScript functions or class components.

  2. The argument to useState is the initial state value. It can be a primitive (e.g., number, string, boolean or object).

  3. useState returns an array with two elements:

    1. [>] the current state value
    2. [>] and a function to update it.
      • 💡 You can use any names for these variables, but common naming conventions are to use stateName and setStateName.

Managing Multiple State Variables

You can use useState multiple times in a component to manage different state variables independently. Here’s an example:

import React, { useState } from 'react';
 
function UserInfo() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
 
  return (
    <div>
      <input
        type="text"
        placeholder="Name"
        value={name}
        onChange={(e) setName(e.target.value)}
      />
      <input
        type="email"
        placeholder="Email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <p>Name: {name}</p>
      <p>Email: {email}</p>
    </div>
  );
}
 
export default UserInfo;
 

In this example, we use two separate useState calls to manage name and email independently.

## State Updates are Asynchronous

It's important to note that state updates in React are asynchronous. If you need to perform actions immediately after a state update, you should use the useEffect hook or pass a callback function to the state updater.

Using Callback Function instead of values.

Passing a function to useState in React instead of a simple value has several advantages, and it’s a recommended practice in certain scenarios.

Lazy Initialization

Lazy Initialization: When you pass a function to useState, React will call that function to initialize the state value only once, the first time the component is rendered. This can be beneficial for expensive or complex initializations that you don’t want to compute on every render. It ensures that the initialization code runs only when needed, improving performance.

Passing a function to useState()

const [count, setCount] = useState(() => {
  // This function is only called once during the initial render.
  return expensiveInitialization()
})

Functional Updates:

When you use the function form of setState (e.g., setCount(prevCount => prevCount + 1)), you can safely update state based on the previous state value. This is particularly useful when you need to calculate the next state based on the current state, as it prevents potential race conditions and ensures that state updates are applied correctly.

const increment = () => {
  setCount((prevCount) => prevCount + 1)
}

USE EFFECT (useEffect)

#useEffect The useEffect hook allows you to perform side effects (like data fetching, manual DOM manipulation, subscriptions, etc.) in functional components.

Some of the few things you would want to do with the useEffect would be

  • 💡 Store Data in local Storage
  • 💡 Call the server to fetch/save data
  • 💡 Manually modify the DOM Element

Basic Usage

At its core, useEffect accepts a function that contains the code to run the side effect:

import { useEffect } from "react"
 
function App() {
  useEffect(() => {
    console.log("This runs after the component is rendered.")
  })
  return <h1>Hello, world!</h1>
}

Dependency Array

The second argument to useEffect is a dependency array. The effect will only re-run if the values in this array change between renders.

useEffect(() => {
  console.log("Runs after every render.")
})

Info Empty Dependency Array: The effect runs once after the initial render (similar to componentDidMount in class components).

useEffect(() => {
  console.log("Runs once after the initial render.")
}, [])
const [count, setCount] = useState(0)
 
useEffect(() => {
  console.log("Count has changed.")
}, [count])

Cleanup with useEffect

Some side effects need cleanup. For instance, if you set up a subscription or event listener, you’d want to remove it when the component is no longer in use. To achieve this, return a function from your effect:

useEffect(() => {
  function handleResize() {
    console.log(window.innerWidth)
  }
  window.addEventListener("resize", handleResize)
  // Cleanup function
  return () => {
    window.removeEventListener("resize", handleResize)
  }
}, [])

useEffect Gotchas & Tips:

  1. Don’t Forget the Dependency Array: Omitting the dependency array or forgetting to include values can lead to bugs that are hard to debug.

  2. Avoid Heavy Operations: If an effect does heavy computations, consider offloading that work to prevent blocking the main thread.

  3. Don’t Put Everything in One Effect: Use multiple useEffect hooks to separate unrelated logic.

  4. Avoid Synchronous Side Effects: React batches updates and handles them asynchronously. Don’t rely on synchronous operations inside useEffect.

  5. Fetching Data: When fetching data, it’s a good practice to manage the loading and error states.

const [data, setData] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
 
useEffect(() => {
  fetch("/api/data")
    .then((response) => response.json())
    .then((data) => setData(data))
    .catch((error) => setError(error))
    .finally(() => setLoading(false))
}, [])
  1. React DevTools: When debugging, the React DevTools browser extension can help you visualize when and how often your effects are running.

Section key takeaways:

#### What you should know about State hooks in react:

  • 💡 State Updates are Asynchronous:
    • ➡️ Not immediately of course,
    • ➡️ When you call the state updater function (e.g., setCount), React schedules a state update, and the new state value may not be immediately available. React batches multiple state updates for performance reasons.
  • 💡 Functional Updates:
    • ➡️ You can also use a functional update when the new state depends on the previous state. Instead of passing a new value directly, you can pass a function that receives the previous state and returns the new state.
setCount((prevCount) => prevCount + 1)
  • 💡 Multiple State Variables:
    • ➡️ You can use useState multiple times in a component to manage multiple state variables.
  • 💡 State is Preserved:
    • ➡️ React ensures that the state is preserved between renders. When the component re-renders, it will have the same state values as before.
  • 💡 Initialization Logic:
    • ➡️ The useState hook should not be called conditionally or inside loops. It should be called at the top level of your component function.

The why it should be called in the top level component is that:

  1. Consistency and Readability:
    • Placing state hooks at the top of your component function creates a consistent and easily recognizable pattern. It makes it clear to other developers (and to your future self) that state is being managed within the component.
  2. Avoiding Conditional Calls:
    • State hooks, like useState, should not be called conditionally within a component. They should be called in the same order on every render. Placing them at the top ensures that they are always called in a consistent manner, avoiding unexpected behavior.
  3. Initialization Logic:
    • State hooks should be called during each render of the component to ensure that the state is correctly initialized. Placing them at the top ensures that they are called on every render.
  4. Predictable Behavior:
    • React relies on the order of hooks to maintain state between renders. Placing state hooks at the top of the component ensures predictable behavior, as React tracks the order in which hooks are called to correctly associate state with components.
  5. Separation of Concerns:
    • Defining state at the top of the component allows you to separate your component’s logic into clear sections. First, you declare your state variables, followed by any other logic, event handlers, and rendering JSX. This separation makes your code more organized and maintainable.
  6. Easier Debugging:
    • When you place state hooks at the top of your component, it’s easier to locate and debug any issues related to state management. You can quickly inspect and modify the state initialization and updates.

Passing data to children via Props

Overview

What are Props?

In React, “props” is short for “properties,” and it’s a way to pass data from a parent component to a child component. Props allow you to make your components reusable and dynamic by providing data and behavior from one component to another.

Using Props

Here’s how you can use props in React components:

import React from "react"
 
// Child component that receives a "name" prop
function Greeting(props) {
  return <p>Hello, {props.name}!</p>
}
 
// Parent component that renders the Greeting component with a "name" prop
function App() {
  return (
    <div>
      <Greeting name="Alice" />
      <Greeting name="Bob" />
    </div>
  )
}
 
export default App
  • 💡 In this example:
    • ➡️ We create a child component called Greeting that accepts a name prop.
    • ➡️ In the parent component App, we render the Greeting component twice, each time with a different name prop value.

Rules for Using Props

  1. Passing Props: To pass a prop to a child component, simply add it as an attribute when rendering the child component.
  2. Accessing Props: In the child component, you can access props by declaring a function parameter (in the example, props), and then use props.propName to access the value of the prop.
  3. Props are Immutable: Props should be treated as read-only. You should never modify a prop directly within the child component. Props are intended to be a one-way communication from parent to child.
  4. Default Props: You can specify default values for props using the defaultProps property if a prop is not provided. Default Props Example
import React from "react"
 
function Greeting(props) {
  return <p>Hello, {props.name}!</p>
}
 
// Setting default props
Greeting.defaultProps = {
  name: "Guest", // Default value for "name" prop if not provided
}
 
function App() {
  return (
    <div>
      <Greeting /> {/* Will display "Hello, Guest!" */}
      <Greeting name="Alice" /> {/* Will display "Hello, Alice!" */}
    </div>
  )
}

export default App; In this example, we set a default value for the name prop using defaultProps in the Greeting component.

Props are a fundamental concept in React that enables you to create reusable and dynamic components by passing data and behavior from parent components to child components. By following these rules and examples, you can effectively use props in your React applications.

Passing functions via props

Passing functions via props in React is a powerful and common practice that allows you to achieve various functionalities and patterns in your application. This approach is fundamental for enabling communication and interaction between parent and child components.

Why Pass Functions via Props?

  1. Component Communication: It facilitates communication between parent and child components. You can pass functions from a parent component to a child component to enable the child component to trigger actions or send data back to the parent.

  2. Reusability: It promotes component reusability. By passing functions as props, you can create child components that are more generic and can be used in various contexts, as they rely on callbacks provided by props.

  3. State Management: It’s essential for managing state in parent components. Parent components can pass down functions to update their state, allowing child components to control or modify data in the parent.

  4. Event Handling: It’s used for handling user interactions. Functions passed as props can be triggered in response to events like button clicks, form submissions, or user input changes.

How It Wo rks

Here’s how passing functions via props works in React:

  1. Define the Function in the Parent Component: In the parent component, define the function you want to pass to the child component. This function typically performs some action or updates the parent’s state.
  2. Pass the Function as a Prop: When rendering the child component, pass the function as a prop by assigning it to an attribute on the child component.
  3. Access and Use the Function in the Child Component: In the child component, you can access the function via the props and call it when needed. This allows the child component to trigger actions in the parent component.

Best Practices and Must-Knows

  • Callback Naming:

    • Choose clear and descriptive names for your callback props to improve code readability and maintainability.
  • Avoid Anonymous Functions:

    • Avoid passing anonymous functions directly as props, as this can lead to unnecessary re-renders. Instead, define the function in the parent component and pass it as a reference.
// Avoid
;<ChildComponent onClick={() => doSomething()} />
 
// Prefer
const handleClick = () => {
  doSomething()
}
 
;<ChildComponent onClick={handleClick} />
  • Bind the Context:

    • Be cautious about the context in which functions are called. If a function relies on the parent’s state or context, ensure that the context is preserved when passing it as a prop.
  • Functional Components:

    • In functional components, use the useCallback hook to memoize functions to prevent unnecessary re-renders when the parent component updates.
  • Document Props:

    • Document the props that are functions in your component’s documentation or with comments to make it clear how they should be used.
  • Prop Validation: - [ ] You can use PropTypes or TypeScript to specify and validate the expected props types, including functions, which can help catch potential issues during development.

    Here’s a simple example illustrating the passing of a function via props:

import React, { useState } from "react"
 
function ParentComponent() {
  const [count, setCount] = useState(0)
 
  const incrementCount = () => {
    setCount(count + 1)
  }
 
  return (
    <div>
      <p>Count: {count}</p>
      <ChildComponent onIncrement={incrementCount} />
    </div>
  )
}
 
function ChildComponent({ onIncrement }) {
  return <button onClick={onIncrement}>Increment Count</button>
}
 
export default ParentComponent

In this example, the incrementCount function is defined in the parent component and passed down to the child component as the onIncrement prop. When the button in the child component is clicked, it triggers the onIncrement function, updating the count in the parent component.

State vs Props

| Props | State | | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | --- | --- | | Input or argument passes to a component. kind of similar to function arguments | Internal Data managed by a component that can change over time. kind of similar to local variables | | Treat this as immutable Don’t change props in the children please.❌ | States on the other hand are mutable, you can change them to your need✅ | | |

They both cause a Cause a re-render of our dom

Passing Children

React provides a special children prop that allows you to pass components or elements as children to a parent component. This is a powerful and flexible feature that is commonly used in React applications to create reusable and composable components.

How the children Prop Works:

  • [/] Passing Components or Elements:
    • 🔖 The children prop allows you to pass React components, elements, or even plain text as children to a parent component. You can use it within the parent component’s JSX to render these children elements.
  • [/] Implicitly Defined:
    • 🔖 React provides the children prop by default for all components.
    • 🔖 You don’t need to explicitly define it in your component’s prop types or as a function parameter.
  • [/] Nested Components:
    • 🔖 You can nest components within each other by placing one component as a child inside another component’s opening and closing tags. These nested components are then accessible via the children prop.
  • [/] Accessing and Rendering:
    • 🔖 To access and render the children elements, you can simply use {props.children} within the parent component’s JSX. This will render whatever elements were passed as children.

Example

function ParentComponent(props) {
  return (
    <div>
      <h2>Parent Component</h2>
      <div className="child-container">{props.children}</div>
    </div>
  )
}
// The App component
function App() {
  return (
    <ParentComponent>
      <p>Child 1</p>
      <p>Child 2</p>
    </ParentComponent>
  )
}

In this example, the ParentComponent receives and renders its children inside a div. When App renders ParentComponent, it includes two paragraphs as children, which are rendered within the div inside ParentComponent.

Must-Know Facts and Best Practices:

  • ➡️ Multiple Children:
    • [/] You can pass multiple children to a parent component, and they will be treated as an array. You can map over them, filter them, or use any array methods as needed.
  • ➡️ Conditional Rendering:
    • [/] You can conditionally render children based on certain conditions within the parent component. This allows you to have dynamic and flexible layouts.
  • ➡️ Prop Drilling:
    • [/] Be cautious of prop drilling when using deeply nested components. If multiple intermediate components don’t need the children prop but have to pass it down, it can lead to complex and less maintainable code. In such cases, consider using React context or a state management library like Redux.
  • ➡️ Default Props:
    • [/] You can provide default children by assigning a default value to the children prop in your component. This can be useful when you want to ensure that there are always some default elements present.
  • ➡️ Composition:
    • [/] The children prop enables component composition, which is a fundamental concept in React. It allows you to build complex UIs by combining simple, reusable components.
  • ➡️ Other Default Props:
    • [/] React does not provide any other default component-specific props like children. The children prop is unique in that it’s implicitly available to all components, and it’s used for passing child components and elements.

Inspecting component with react Dev tools

Updating Objects

Updating objects in React (or JavaScript in general) involves creating a new object with updated values rather than modifying the existing object directly. This approach is known as immutability and is crucial for ensuring predictable and efficient updates in React components

Techniques for updating.

Using the Spread Operator (...):

The spread operator (...) is a common and convenient way to create a new object with updated properties or values from an existing object.

// Original object
const person = {
  name: "John",
  age: 30,
}
 
// Update a property (age) with a new value
const updatedPerson = { ...person, age: 31 }
// Create a new object with an additional property
const extendedPerson = { ...person, email: "john@example.com" }
 
// Objects
const [drink, setDrink] = useState({
  name: "Ilunga",
  address: {
    country: "Rwanda",
    zipCode: 941111,
  },
})
// Update logic
setDrink({ ...drink, address: { ...drink.address, zipCode: 666 } })
// Sample array of objects
const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
  { id: 3, name: "Charlie" },
]
 
// Adding an object to the array
const newUser = { id: 4, name: "David" }
const updatedUsersWithNewUser = [...users, newUser]
 
// Removing an object from the array by ID
const idToRemove = 2
const updatedUsersWithoutRemovedUser = users.filter((user) => user.id !== idToRemove)
 
// Updating an object in the array by ID
const idToUpdate = 3
const updatedUsersWithUpdatedUser = users.map((user) => {
  if (user.id === idToUpdate) {
    // Create a new object with the updated values
    return { ...user, name: "UpdatedCharlie" }
  }
  return user
})
 
// Displaying the updated arrays
console.log("Original Users:", users)
console.log("Updated Users with New User:", updatedUsersWithNewUser)
console.log("Updated Users without Removed User:", updatedUsersWithoutRemovedUser)
console.log("Updated Users with Updated User:", updatedUsersWithUpdatedUser)

Using Object.assign():

Object.assign() is another method for creating a new object with updated properties. It takes the target object (where properties are copied to) and one or more source objects (from which properties are copied).

const person = {
  name: "John",
  age: 30,
}
const updatedPerson = Object.assign({}, person, { age: 31 })

Using the Spread Operator with Nested Objects:

When dealing with nested objects, you need to ensure that you create new objects at all levels to maintain immutability. Here’s an example:

const user = {
  id: 1,
  info: {
    name: "Alice",
    age: 25,
  },
}
// Update a property within a nested object
const updatedUser = {
  ...user,
  info: {
    ...user.info,
    age: 26,
  },
}

## Using the Immer library to do the dirty job for you!

You can Immer to mutate your object and create a copy of it!

// setDrink(
//   drink.map((d) => {
//     return d ? { ...d, false: true } : d;
//   })
// );
setDrink(
  produce((draf) => {
    const bug = draf.find((bg) => bg.name === "daniel")
    if (bug) bug.name = "Hello You"
  }),
)

Form

Forms are a fundamental part of web development, allowing users to input data and interact with web applications. React provides a powerful way to handle forms using controlled components.

React forms are slightly different from regular HTML forms. Instead of reading values from the DOM directly, React uses a process called "controlled components." This means the form input element values are controlled by React's state.

Creating a Form

To create a form in React, you start by adding an HTML <form> element to your component’s JSX. This element will contain all your form inputs and elements.

<form> {/* Form inputs go here */} </form>

Form Input Elements

React allows you to use various form input elements such as text inputs, checkboxes, radio buttons, selects, and more. Each input element can be controlled by React state, ensuring that the form data is synchronized with your component’s state.

Text Input

<input type="text" value={value} onChange={handleChange} />

Handling Multiple Inputs

If you have multiple input elements, you can use the name attribute and a single state object to handle them:

function Form() {
  const [formData, setFormData] = useState({
    name: "",
    email: "",
  })
 
  const handleChange = (event) => {
    const { name, value } = event.target
    setFormData((prevData) => ({
      ...prevData,
      [name]: value,
    }))
  }
 
  return (
    <form>
      <input name="name" value={formData.name} onChange={handleChange} />
      <input name="email" type="email" value={formData.email} onChange={handleChange} />
      {/* ... */}
    </form>
  )
}

Checkbox

const [isChecked, setIsChecked] = useState(false)
 
;<input type="checkbox" checked={isChecked} onChange={(e) => setIsChecked(e.target.checked)} />

Radio Buttons

const [selectedOption, setSelectedOption] = useState('');
 
<input
  type="radio"
  value="option1"
  checked={selectedOption === 'option1'}
  onChange={(e) => setSelectedOption(e.target.value)}
/>
<input
  type="radio"
  value="option2"
  checked={selectedOption === 'option2'}
  onChange={(e) => setSelectedOption(e.target.value)}
/>
 

Select Dropdown

const [selectedValue, setSelectedValue] = useState("")
 
;<select value={selectedValue} onChange={(e) => setSelectedValue(e.target.value)}>
  <option value="option1">Option 1</option>
  <option value="option2">Option 2</option>
</select>

Form validation

React doesn’t have built-in form validation, but you can easily add your logic:

function Form() {
  const [email, setEmail] = useState("")
  const [errors, setErrors] = useState({})
 
  const handleSubmit = (event) => {
    event.preventDefault()
 
    if (!email.includes("@")) {
      setErrors({ email: "Invalid email address." })
      return
    }
    // Submit the form data...
  }
 
  return (
    <form onSubmit={handleSubmit}>
      <input name="email" value={email} onChange={(e) => setEmail(e.target.value)} />
      {errors.email && <p>{errors.email}</p>}
      {/* ... */}
    </form>
  )
}

Handling Form Submission

To handle form submission, attach an onSubmit event handler to the form element. In the event handler, you can prevent the default form submission behavior, process the form data, and perform any necessary actions.

<form onSubmit={handleSubmit}>
  {/* Form inputs go here */}
  <button type="submit">Submit</button>
</form>

Controlled Components

Controlled components in React are a key concept in form handling. They ensure that the form data is controlled by React state. To create a controlled component:

  • ➡️ Initialize a state variable to hold the form data.
  • ➡️ Set the value of the form elements to the state variable.
  • ➡️ Provide event handlers (onChange) to update the state when the user interacts with the form elements.
const [inputValue, setInputValue] = useState("")
;<input type="text" value={inputValue} onChange={(e) => setInputValue(e.target.value)} />

Form Validation

Form validation is essential to ensure that the data submitted by users is correct and meets certain criteria. You can perform validation in your event handlers and provide feedback to the user.

const [inputValue, setInputValue] = useState("")
const [error, setError] = useState("")
 
const handleInputChange = (e) => {
  const value = e.target.value
  setInputValue(value)
 
  if (!value.trim()) {
    setError("Field cannot be empty")
  } else {
    setError("")
  }
}

Form Best Practices

  • Use controlled components to keep form data in sync with React state.
  • Break down complex forms into smaller, reusable components.
  • Provide clear error messages for validation failures.
  • Use form libraries like formik or react-hook-form for more advanced form handling.
  • Consider accessibility when designing forms (e.g., provide labels, use proper semantic HTML elements).
  • Avoid using the ref attribute to directly manipulate form elements; prefer state management.

Debouncing

Debouncing is a technique to limit the number of times a function gets executed over time. When applied to inputs, debouncing can improve performance, especially in scenarios where you want to perform some real-time operations based on the input value, like fetching suggestions in a search box.

Common Form Gotchas

  • 🔥 Forgetting to prevent the default form submission behavior using e.preventDefault() in your onSubmit handler.
  • 🔥 Not initializing state variables with appropriate default values.
  • 🔥 Failing to provide unique name attributes for radio buttons to group them correctly.
  • 🔥 Neglecting to handle different input types (e.g., checkboxes, selects) differently in your onChange handlers.

Tips, Tricks, and Gotchas :

  • [p] Debounce Input
    • ➡️ : For text inputs, especially search boxes, use a debounce function to delay processing the input until the user stops typing.
  • [p] Avoid Inline Validations:
    • ➡️ Inline validations (validating as the user types) can be disruptive. Consider validating onBlur (when the user moves to the next input) or on form submission.
  • [p] Always Use e.preventDefault() in Form Submits:
    • ➡️ By default, forms will refresh the page on submission. To prevent this default behavior, always use e.preventDefault().
  • [p] Resetting a Form:
    • ➡️ To reset a form, set the state to its initial value.
  • [p] Uncontrolled Components & useRef:
    • ➡️ In some cases, you might want to use uncontrolled components (inputs not controlled by React state). Use the useRef hook to access these inputs. However, controlled components are more in the “React” way and are recommended.
  • [p] Third-party Libraries:
    • ➡️ If your form logic becomes too complex, consider using libraries like Formik or React Hook Form.
  • [p] Accessibility (a11y):
    • ➡️ Ensure that your form elements have proper labels (use the label tag or aria-label attribute). This is crucial for screen reader users.

UseRef

The useRef hook is a versatile tool in React for interacting with the DOM and managing references to components and elements.

What is useRef?

useRef is a React hook that provides a mutable ref object. Unlike useState, it doesn’t cause re-renders when its value changes. Instead, it allows you to interact with and store references to DOM elements or components across renders. This makes it useful for managing imperative logic and side effects in your components.

2. When to Use useRef

You should consider using useRef in the following scenarios:

  • ➡️ DOM Interaction:
    • When you need to interact with DOM elements directly, such as setting focus, measuring dimensions, or accessing properties not managed by React.
  • ➡️ Storing Mutable Values:
    • To store values that don’t trigger re-renders but need to persist between renders (e.g., for caching or to hold previous values).
  • ➡️ Managing External Resources:
    • For managing external resources like timers, animations, or subscription handles that need to persist across component renders.

How to use useRef

import { useRef } from 'react';
function MyComponent() {
  // Create a ref object
  const myRef = useRef(initialValue);
  // Access the current value of the ref
  const currentRefValue = myRef.current;
  return (
    // JSX and component logic
  );
}

Imperative DOM Interaction

import { useRef, useEffect } from "react"
function FocusInput() {
  const inputRef = useRef(null)
  useEffect(() => {
    // Set focus to the input element on mount
    inputRef.current.focus()
  }, [])
  return <input ref={inputRef} />
}

Storing Previous Values

import { useRef, useEffect } from "react"
 
function Counter() {
  const count = useRef(0)
 
  useEffect(() => {
    const timerId = setInterval(() => {
      count.current += 1
      console.log(`Count: ${count.current}`)
    }, 1000)
    return () => clearInterval(timerId)
  }, [])
  return <div>Counter: {count.current}</div>
}

Connecting to a Backend

#fetch

# You need to understand The useEffect Hook first

Tips and tricks

The Mirage Dilemma

Sometimes when you are using the mirage server, you might end up facing with redirection issues, this is likely to happen if you are using react router v 6.16.4

Mirage redirection problem

Your code might look like this , and you be asking yourself why it is not workin g

const isLoggedIn = false
if (!isLoggedIn) {
  // This might not work in Mirage Server 🥲
  throw redirect("/login")
}

To fix the this annoying our of proportion error you can simply set the body to true before throwing your erro

const redirection: any = redirect("/login")
redirection.body = true
throw redirection

Suspense

The <Suspense> lets you display a fallback until its children have finished loading.

<Suspense fallback={<Loading />}>
  <SomeComponent />
</Suspense>

Suspense 

Props

  • ➡️ children:
    • 💡 The actual UI you intend to render. If children suspends while rendering, the Suspense boundary will switch to rendering fallback.
  • ➡️ fallback:
    • 💡 An alternate UI to render in place of the actual UI if it has not finished loading. Any valid React node is accepted, though in practice, a fallback is a lightweight placeholder view, such as a loading spinner or skeleton. Suspense will automatically switch to fallback when children suspends, and back to children when the data is ready. If fallback suspends while rendering, it will activate the closest parent Suspense boundary.

Must check React related libs/addOns

  • Izzedin

    • React Router
    • React Query
  • Ivad

    • className
    • useHooks
  • Christian

    • React Router
    • React Query
  • Aristide

    • Gsap
    • React type writer
      • React Spring
  • Moussa

    • React hook form
      • Zod
  • Josh

    • Route
    • Query
      • Axios
  • Aline

    • React router
    • React Query
  • Junior

    • Framer Motion
  • Ibrahim

    • React Router
    • React hook form
  • Outside of react ,

  • Will always get triggered when component render