A Glance at State Hooks in React


A Glance at State Hooks in React

Hooks vs. Class Components

Hooks make your react code look simpler. Take a counter program as an example.
Using class components:

import React from "react";

class ClassComponent extends React.Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };
    this.increase = this.increase.bind(this);
  }

  increase() {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <h1>{this.state.count}</h1>
        <button onClick={this.increase}>+</button>
      </div>
    );
  }
}

export default ClassComponent;

But with hooks, one can import useState first and instead of creating a class.

import React, { useState } from "react";

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

  function increase() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={increase}>+</button>
    </div>
  );
}

export default FunctionalComponent;

Hooks provide a more direct API to the React concepts like props, state, context, refs, and lifecycle. There are a variety of hooks available: 1. that can store data (e.g. useState,useReducer) and connect data with lifecycle; 2. that can provide some memory functionality (e.g. useMemo,useCallback) so we can store some values in the previous execution; 3. that can provide more control (e.g. useEffect,useRef, useContext) so we have a extensive access and control inside React.

Example: Clock with State Hooks

Here is an example using state hooks to update a clock every one second. with setInterval(updateTime, 1000);. The const [time, setTime] line follows the JavaScript syntax called array destructuring. One can think the time as this.state.time and setTime as this.setState in a class.

import React, { useState } from "react";

function App() {
  setInterval(updateTime, 1000);
  const [time, setTime] = useState(new Date().toLocaleTimeString("en-GB"));
  function updateTime() {
    const newTime = new Date().toLocaleTimeString("en-GB");
    setTime(newTime);
  }
  return (
    <div className="container">
      <h1>{time}</h1>
      <button onClick={updateTime}>Get Time</button>
    </div>
  );
}

export default App;

Example: To-Do List using State Hooks and Props

Below is a to-do list (source code: codesandbox). The App component (shown below) contains two components - InputArea and ToDoItem. items is the array used to store items showing on the screen, setItems is the function we use to update the items. Since we just want to add / delete an item from items but not to create a new array every time, we can work on the previous state with React hook and use spread operator in JS ES6 to extend the array or use filter method to delete the item that is clicked.

App.jsx
import React, { useState } from "react"; import ToDoItem from "./ToDoItem"; import InputArea from "./InputArea"; function App() { const [items, setItems] = useState([]); function addItem(inputText) { setItems((prevItems) => { return [...prevItems, inputText]; }); } function deleteItem(id) { setItems((prevItems) => { return prevItems.filter((item, index) => { return index !== id; }); }); } return ( <div className="container"> <div className="heading"> <h1>To-Do List</h1> </div> <InputArea onAdd={addItem} /> <div> <ul> {items.map((todoItem, index) => ( <ToDoItem key={index} id={index} text={todoItem} onChecked={deleteItem} /> ))} </ul> </div> </div> ); } export default App;

InputArea (shown below) contains inputText which stores the text typed in the input. It is updated by the onChange‘s handleChange in the input element. What interesting is the onClick inside the button element. It allows us to add what we just typed into the array defined in App.jsx. If we take a closer look, the onAdd which carries addItem is passed from App.jsx (Yes! We can pass functions as props). Since we don’t want the addItem executed immediately when the page gets rendered, we write line 14-16 using the arrow operator.

InputArea.jsx
import React, { useState } from "react"; function InputArea(props) { const [inputText, setInputText] = useState(""); function handleChange(event) { const newValue = event.target.value; setInputText(newValue); } return ( <div className="form"> <input onChange={handleChange} type="text" value={inputText} /> <button onClick={() => { props.onAdd(inputText); setInputText(""); }} > <span>Add</span> </button> </div> ); } export default InputArea;

Similarly, in ToDoItem.jsx (shown below) the props.onChecked was passed from App.jsx and it’s the function deleteItem. Since props.onChecked is called from ToDoItem.jsx, we also need to pass the id from App.jsx to ToDoItem.jsx using props so we can delete that item properly.

ToDoItem.jsx
import React from "react"; function ToDoItem(props) { return ( <div onClick={() => { props.onChecked(props.id); }} > <li>{props.text}</li> </div> ); } export default ToDoItem;

Author: Black Vinegar
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Black Vinegar !
评论
  TOC