Adding Interactivity in React

Adding Interactivity in React

Reactjs series from beginner to advanced level ep9

Interactivity can be added to a website or application by incorporating elements such as buttons, forms, and links that allow users to interact with the content and navigate the site. JavaScript can be used to create dynamic effects and add interactivity to a website, such as image sliders, drop-down menus, and modal windows. Additionally, interactive elements such as games and quizzes can be added to a website using JavaScript and other programming languages. Another way to add interactivity is through the use of a JavaScript library such as React or Angular, which provides a framework for building interactive user interfaces.

Responding to events

n React, event handling is typically done by passing a callback function as the value of an event handler attribute, such as onClick, onChange, or onSubmit. The callback function is then invoked when the event occurs.

Here is an example of a simple button component that uses an onClick event handler:

import React from 'react';

function MyButton({ onClick }) {
  return <button onClick={onClick}>Click me!</button>;
}

export default MyButton;

And in the parent component you can use it like this:

import MyButton from './MyButton';

function App() {
  const handleClick = () => {
    console.log('Button was clicked!');
  };

  return <MyButton onClick={handleClick} />;
}

This way, when the button is clicked, the handleClick function will be called.

You can also use arrow function to directly handle the event and perform an action, like this:

import React from 'react';

function MyButton() {
  return <button onClick={()=>console.log("Button Clicked")}>Click me!</button>;
}

export default MyButton;

It's also possible to use a class component and bind the event handler to the component's this context.

You can also use event.preventDefault() inside the callback function to prevent the default behaviour of the event.

State: a component’s memory

State in React is an object that holds information about a component's current state or condition. It allows a component to keep track of its own data and update itself based on that data.

State is used to store information that can change within a component, such as user input, form values, or the current state of a toggle button. The state can be updated using the setState() method, which triggers a re-render of the component and updates the UI to reflect the new state.

A component's state is private to that component and cannot be accessed or modified by other components. This allows for a more modular and maintainable codebase, as each component can manage its own state independently of other components.

It's important to note that state should only be used when it's necessary to keep track of data that changes within a component, and not for data that is passed down from parent components. In those cases, it's better to use props (properties) instead.

Example:

import { useState } from 'react';

const MyInput = () => {
  const [inputValue, setInputValue] = useState("");

  const handleChange = (event) => {
    setInputValue(event.target.value);
  }

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={handleChange}
      />
      <p>{`Current input value: ${inputValue}`}</p>
    </div>
  );
}

In this example, we create a functional component called "MyInput" which uses the useState hook to create a state variable called "inputValue". This state variable is used to store the current value of the input field.

We also have a function called "handleChange" which is passed as the onChange prop to the input element. When the input value changes, the handleChange function will be called, and it updates the state with the new value, this will cause the component to re-render and update the UI.

The component also displays the current value of the input field in a <p> tag, which is accessed through the component's state.

Render and commit

The render and commit steps in React can be compared to the process of ordering food at a restaurant.

  1. The Render Step: Imagine a customer sitting at a table, looking at the menu and deciding what to order. This is similar to the render step in React, where the component is deciding what its next appearance should be based on its props and state. Just like the customer, the component is reviewing its options and makes decisions on what should be displayed.

  2. The Commit Step: Once the customer has decided on their order, they would flag down the waiter and tell them what they would like to order. This is similar to the commit step in React, where the component is updating the actual DOM elements and updating its appearance on the screen. The waiter, just like the React commit step, is responsible for taking the customer's order and relaying it to the kitchen.

  3. The process of ordering food would repeat once the customer is ready to order more food or when the customer is finished eating. Similarly, React will keep running the render and commit steps every time there's an update or an event that would trigger another render and commit cycle.

  4. The lifecycle methods in React, such as componentDidMount, componentDidUpdate, and componentWillUnmount, can be compared to the waiter's tasks such as taking the order, bringing the food to the table, and cleaning up the table after the customer is finished eating.

Imagine that your components are cooks in the kitchen, assembling tasty dishes from ingredients. In this scenario, React is the waiter who puts in requests from customers and brings them their orders. This process of requesting and serving UI has three steps:

  1. Triggering a render (delivering the diner’s order to the kitchen)

  2. Rendering the component (preparing the order in the kitchen)

  3. Committing to the DOM (placing the order on the table)

State as a snapshot

React state can be thought of as a snapshot of the component's current condition or data. It captures the component's internal state at a particular point in time and reflects the current status of the component.

Just like a snapshot, the state is a representation of the component's current state and it can change based on user interactions, events, or other factors. For example, a component's state may change when the user inputs text into a form, or when a button is clicked.

Just like a snapshot, the state can be captured and saved for later use. This is useful for implementing features such as undo and redo, or for persisting data across multiple sessions.

In addition, just like a snapshot, the state can be used to restore the component to a previous state. This allows you to easily revert the component to a previous state, or to restore the state after a page refresh.

React's state management system is built around this idea of a snapshot. It allows you to easily capture, update, and restore the state of a component as needed, making it a powerful tool for building dynamic and responsive user interfaces.

Updating objects in state

In many programming languages, including JavaScript and React, updating an object in state is done by creating a copy of the state object and then updating the copy with the new values. This is done to ensure that the original state object is not modified directly, which can lead to unexpected behavior.

For example, in React, you can use the setState method to update the state object and re-render the component. The method takes an object that contains the updates to be made to the state:

Here's an example of how you can use useState to manage the state of an object in a functional component:

import { useState } from 'react';

function MyComponent() {
  const [myObject, setMyObject] = useState({
    name: "John",
    age: 20
  });

  const handleClick = () => {
    setMyObject({
      ...myObject,
      name: "new name",
      age: 25
    });
  }

  return (
    <div>
      <p>Name: {myObject.name}</p>
      <p>Age: {myObject.age}</p>
      <button onClick={handleClick}>Update</button>
    </div>
  );
}

In this example, useState is used to create a state variable myObject with an initial value of an object containing name and age. The setMyObject function is used to update the state when the button is clicked. Note that as in class based component, it's important to use the spread operator to create a new copy of the object before updating it, otherwise the original object will be modified and it can lead to unexpected behavior.

When the handleClick function is called, it creates a new object with the updated values, and then calls setMyObject to update the state and re-render the component.

Updating arrays in state

In React, updating an array in state is done by creating a copy of the array and then updating the copy with the new values. This is done to ensure that the original state array is not modified directly, which can lead to unexpected behaviour.

In functional component, you can use the useState hook to manage state of an array and use the spread operator to create a new copy of the array before updating it:

import { useState } from 'react';

function MyComponent() {
  const [myArray, setMyArray] = useState([1, 2, 3]);

  const handleClick = () => {
    setMyArray([...myArray, 4]);
  }

  return (
    <div>
      <p>{myArray.join(', ')}</p>
      <button onClick={handleClick}>Add</button>
    </div>
  );
}

It's important to note that, when updating an array, it's best to avoid directly modifying the state array (e.g. using push, splice, etc.) and instead, use functional approaches like concat, map, filter, etc.

Conclussion

In conclusion, handling user-initiated events, managing state, and understanding how React updates the UI are crucial concepts for building efficient and effective React applications. By using state, components can "remember" information and make decisions based on that data. React updates the UI in two phases, rendering and committing, which helps to ensure that updates are made efficiently and without causing unnecessary re-renders. Additionally, state may not update immediately after a change due to the way React handles updates, but this can be addressed by queuing multiple state updates or using the appropriate methods for updating objects and arrays in state. Overall, understanding these concepts and best practices will lead to a more seamless and optimized user experience in React applications.