Full Stack Development

useState and Hooks

by Tomas Trescak t.trescak@westernsydney.edu.au

Reactivity

/

Introduction

      import { useState, render } from 'react';

function Counter() {
  const [value, setValue] = useState(0);
  
  function inc() {
    setValue(value + 1);
  }
  
  return (
    <div>
      Counter: {value}
      <button onClick={inc}>+</button>
    </div>
  )
}

render(<Counter />)
    

Reactivity

Hooks

  • useState
    controls the state and reactivity of the component
  • useEffect
    controls the side effects and clean up
  • useMemo
    remembers values of expensive computations
  • ... and more
    import { Component, useState } from React;

class MyComponent extends Component {
    state = { count: 1 };
    render() {
        return <div>Count {this.state.count}</div>
    }
}

function MyComponent() {
    const [count, setCount] = useState(1)
    return (
        <div>Count {count}</div>
    )
}

  

Reactivity

/

useState

      import { useState, render } from 'react';

function Counter() {
  const [value, setValue] = useState(0);
  
  function inc() {
    setValue(value + 1);
  }
  
  return (
    <div>
      Counter: {value}
      <button onClick={inc}>+</button>
    </div>
  )
}

render(<Counter />)
    

Reactivity

/

useState

      import { useState, render } from 'react';

function Counter() {
  const [value, setValue] = useState(0);
  
  function inc() {
    setValue(value + 1);
  }
  
  return (
    <div>
      Counter: {value}
      <button onClick={inc}>+</button>
    </div>
  )
}

render(<Counter />)
    

Reactivity

/

state with Array

      import { useState, render } from 'react';

function Names() {
  const [names, setNames] = useState(["Tomas"]);
  
  function insertName() {
    names.push("Valeria");
    setNames(names)
  }
  
  return (
    <div>
      {names.join(", ")}
      <button onClick={insertName}>+</button>
    </div>
  )
}

render(<Names />)
    

Reactivity

/

state with Objects

      import { useState, render } from 'react';

function Card() {
  const [person, setPerson] = useState({ 
    name: "Tomas", 
    age: 44 
  });
  
  function increaseAge() {
    person.age += 1;
    setPerson(person);
  }
  
  return (
    <div>
      Name: { person.name  }<br />
      Age: { person.age }
      <button onClick={increaseAge}>+</button>
    </div>
  )
}

render(<Card />)
    

Reactivity

/

🪝 Custom Hooks

      import { useState, render } from 'react';

type Person = { 
  name: string, 
  gender: string, 
  age: number  
}

function usePersonData(partial: Partial<Person>) {
  const [person, setPerson] = useState<Person>({
    name: "John",
    gender: "male",
    age: 0,
    ...partial
  })
  
  return {
    person,
    setPerson,
    setPartialPerson(partial: Partial<Person>) {
        setPerson({ ...person, ...partial })
    }
  }
}

function NameList() {
  const { 
    person, 
    setPartialPerson 
  } = usePersonData({ name: "Tomas", age: 44 });
  
  function increaseAge() {
    setPartialPerson({
        age: person.age + 1
    })
  }
  
  return (
    <div>
        Name: { person.name  }<br />
        Age: { person.age }
        <button onClick={increaseAge}>+</button>
    </div>
  )
}

render(<NameList />)
    

🪝

Rules of Hooks

/

Rule #1

      import { useState, render } from 'react';
const [count, setCount] = useState(0)

function App() {
    return <div>{count}</div>
}

render(<App />)
    

🪝

Rules of Hooks

/

Rule #1

      import { useState, render } from 'react';

function App() {
    const [count, setCount] = useState(0)
    return <div>{count}</div>
}

render(<App />)
    

🪝

Rules of Hooks

/

Rule #1

      import { useState, render } from 'react'
function useCounter() {
    const [count, setCount] = useState(0)
    return { count, setCount }
} 

function App() {
    const { count } = useCounter();
    return <div>{count}</div>
}

render(<App />)
    

🪝

Rules of Hooks

/

Rule #2

      import { useState, render } from 'react'

function App() {
  const [count, setCount] = useState(0)
  
  if (count > 1) {
    const [double, setDouble] = useState(count * 2)
     return (
      <div onClick={() => setDouble(double * 2)}>
        {double}
      </div>
     )
  }
  return (
    <>
      Count:  { count}
      <button onClick={() => setCount(count + 1)}>
        +
      </button>
    </>
  )
}

render(<App />)
    

🪝

Rules of Hooks

/

Rule #2

      import { useState, render } from 'react'

function Doubler({ count }) {
  const [double, setDouble] = useState(count)
  return (
   <>
      Double:  { double }
      <button onClick={() => setDouble(double * 2)}>
        +
      </button>
    </>
  )
}

function App() {
  const [count, setCount] = useState(0)
  
  if (count > 1) {
    return <Doubler count={count} />
  }
  return (
    <>
      Count:  { count}
      <button onClick={() => setCount(count + 1)}>
        +
      </button>
    </>
  )
}

render(<App />)
    

useState

/

Batching

      import React, { render, useState } from "react";

const BatchingDemo = () => {
  const [count1, setCount1] = useState(0);
  const [count2, setCount2] = useState(0);

  console.log("Rendering");

  const handleClick = () => {
    console.log(
      `Before Updates: ${count1}, ${count2}`
    );

    // Multiple state updates in one event
    setCount1((prev) => prev + 1);
    setCount2((prev) => prev + 1);

    console.log(
      `After Updates:, ${count1}, ${count2}`
    );
  };

  return (
    <div>
      <h1>React State Batching Example</h1>
      <p>Count 1: {count1}</p>
      <p>Count 2: {count2}</p>
      <button onClick={handleClick}>Increment Both</button>
    </div>
  );
};

render(<BatchingDemo />);