A counter using useEffect and useReducer

0

import React, { useReducer, useEffect } from "react";

function IntervalCounter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  const { count, step } = state;

  useEffect(() => {
    const id = setInterval(() => {
      dispatch({ type: 'tick' });
    }, 1000);
    return () => clearInterval(id);
  }, [dispatch]);

  return (
    <>
      <h1>{count}</h1>
      <label for="stepInput">Amount to add each second:</label>
      <input id="stepInput" value={step} onChange={e => {
        dispatch({
          type: 'step',
          step: Number(e.target.value)
        });
      }} />
    </>
  );
}

const initialState = {
  count: 0,
  step: 1,
};

function reducer(state, action) {
  const { count, step } = state;
  if (action.type === 'tick') {
    return { count: count + step, step };
  } else if (action.type === 'step') {
    return { count, step: action.step };
  } else {
    throw new Error();
  }
}

export default IntervalCounter;

Counter that randomly changes color on change:

0

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

function IntervalCounterColor() {
  const [count, setCount] = useState(0);
  const [step, setStep] = useState(1);
  const [color, setColor] = useState('white');
  const colors = ['blue', 'red', 'green','yellow','purple','pink','aqua'];

  useEffect(() => {
    const id = setInterval(() => {
      setCount(c => c + step);
      setColor(colors[Math.floor(Math.random() * 7)]);
    }, 1000);
    return () => clearInterval(id);
  }, [step]);

  return (
    <>
      <h1><span style={{background: color, padding:'.25em .5em'}}>{count}</span></h1>
      <label for="countInput">Amount to add each second:</label>
      <input id="countInput" value={step} onChange={e => setStep(Number(e.target.value))} />
    </>
  );
}

export default IntervalCounterColor;

From: overreacted.io blog


I'm adding to two counts, but only one makes me change colour: a=0 and b=0
import React, {useEffect, useState} from 'react'

function PropChangeWatch({ a, b }) {
    const [color, setColor] = useState('white');
    const colors = ['lightblue', 'red', 'lightgreen','yellow','lavender','pink','aqua'];
    useEffect(() => {
      console.log("value of 'a' changed to", a);
      setColor(colors[Math.floor(Math.random() * 7)]);
    }, [a]);
  
    return (
      <div style={{backgroundColor: color}}>
        I'm adding to two counts, but only one makes me change colour: a={a} and b={b}
      </div>
    );
  }
  
  function PropsUpdate() {
    const [count1, setCount1] = useState(0);
    const [count2, setCount2] = useState(0);
  
  
    return (
      <div>
        <PropChangeWatch a={count1} b={count2} />
        <button onClick={() => setCount1(count1 + 1)}>Add 1 to the value of a</button>
        <button onClick={() => setCount2(count2 + 1)}>Add 1 to the value of b</button>
      </div>
    );
  }

  export default PropsUpdate;

From an example on Dave Ceddia's Blog


App that calculates factors of a number, and can also toggle theme

useEffect with useCallback to prevent re-rendering of list when only Theme (dark mode) changes:

0Count of useEffect Triggers (ie list of factors re-calculated and re-rendered)

    useEffect without memoization to prevent re-rendering of list when only Theme (dark mode) changes:

    0Count of useEffect Triggers (ie list of factors re-calculated and re-rendered)

      From Vaishnav's Blog