Mastering React Advanced Hooks with TypeScript: Simulating a Dynamic Equation System

Mastering React Advanced Hooks with TypeScript: Simulating a Dynamic Equation System In today’s React applications, advanced hooks like useContext, useReducer, and useLayoutEffect provide powerful tools to manage state, coordinate rendering, and share data efficiently—without introducing excessive boilerplate. In this article, we’ll implement these hooks in a real-world mathematical scenario: simulating a system of equations with shared coefficients and synchronized updates using React + TypeScript. Objective: Simulate and Manage Dynamic Equations We’ll create a dynamic environment with: Global equation context using useContext State transitions and actions using useReducer Layout synchronization using useLayoutEffect to ensure DOM alignment before render Hook Overview in this Context Hook Purpose useContext Share coefficients across components useReducer Manage complex state transitions like equation switching useLayoutEffect Ensure the canvas and equation list align correctly before paint Step 1: Define Global Math Context // MathContext.tsx import React, { createContext, useReducer, useContext } from "react"; type Equation = { id: string; formula: string; coefficients: number[]; }; type State = { activeEquation: Equation; }; type Action = | { type: "SET_EQUATION"; payload: Equation }; const initialState: State = { activeEquation: { id: "eq1", formula: "y = ax² + bx + c", coefficients: [1, 2, 1] } }; const MathContext = createContext(undefined); function mathReducer(state: State, action: Action): State { switch (action.type) { case "SET_EQUATION": return { ...state, activeEquation: action.payload }; default: return state; } } export const MathProvider: React.FC = ({ children }) => { const [state, dispatch] = useReducer(mathReducer, initialState); return ( {children} ); }; export const useMath = () => { const context = useContext(MathContext); if (!context) throw new Error("useMath must be used within MathProvider"); return context; }; Step 2: Visualizing the Equation import { useLayoutEffect, useRef } from "react"; import { useMath } from "./MathContext"; export const EquationVisualizer = () => { const canvasRef = useRef(null); const { state } = useMath(); const [a, b, c] = state.activeEquation.coefficients; useLayoutEffect(() => { const canvas = canvasRef.current; const ctx = canvas?.getContext("2d"); if (!canvas || !ctx) return; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); for (let x = -100; x ; }; Step 3: Dynamic Equation Switching const EquationSelector = () => { const { dispatch } = useMath(); const handleChange = () => { dispatch({ type: "SET_EQUATION", payload: { id: "eq2", formula: "y = 2x² - 3x + 5", coefficients: [2, -3, 5] } }); }; return Switch Equation; }; App Component import { MathProvider } from "./MathContext"; import { EquationVisualizer } from "./EquationVisualizer"; import { EquationSelector } from "./EquationSelector"; export const App = () => (

May 17, 2025 - 00:02
 0
Mastering React Advanced Hooks with TypeScript: Simulating a Dynamic Equation System

Mastering React Advanced Hooks with TypeScript

Mastering React Advanced Hooks with TypeScript: Simulating a Dynamic Equation System

In today’s React applications, advanced hooks like useContext, useReducer, and useLayoutEffect provide powerful tools to manage state, coordinate rendering, and share data efficiently—without introducing excessive boilerplate.

In this article, we’ll implement these hooks in a real-world mathematical scenario: simulating a system of equations with shared coefficients and synchronized updates using React + TypeScript.

Objective: Simulate and Manage Dynamic Equations

We’ll create a dynamic environment with:

  • Global equation context using useContext
  • State transitions and actions using useReducer
  • Layout synchronization using useLayoutEffect to ensure DOM alignment before render

Hook Overview in this Context

Hook Purpose
useContext Share coefficients across components
useReducer Manage complex state transitions like equation switching
useLayoutEffect Ensure the canvas and equation list align correctly before paint

Step 1: Define Global Math Context

// MathContext.tsx
import React, { createContext, useReducer, useContext } from "react";

type Equation = {
  id: string;
  formula: string;
  coefficients: number[];
};

type State = {
  activeEquation: Equation;
};

type Action =
  | { type: "SET_EQUATION"; payload: Equation };

const initialState: State = {
  activeEquation: {
    id: "eq1",
    formula: "y = ax² + bx + c",
    coefficients: [1, 2, 1]
  }
};

const MathContext = createContext<{ state: State; dispatch: React.Dispatch<Action> } | undefined>(undefined);

function mathReducer(state: State, action: Action): State {
  switch (action.type) {
    case "SET_EQUATION":
      return { ...state, activeEquation: action.payload };
    default:
      return state;
  }
}

export const MathProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [state, dispatch] = useReducer(mathReducer, initialState);
  return (
    <MathContext.Provider value={{ state, dispatch }}>
      {children}
    MathContext.Provider>
  );
};

export const useMath = () => {
  const context = useContext(MathContext);
  if (!context) throw new Error("useMath must be used within MathProvider");
  return context;
};

Step 2: Visualizing the Equation

import { useLayoutEffect, useRef } from "react";
import { useMath } from "./MathContext";

export const EquationVisualizer = () => {
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const { state } = useMath();
  const [a, b, c] = state.activeEquation.coefficients;

  useLayoutEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas?.getContext("2d");
    if (!canvas || !ctx) return;

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.beginPath();

    for (let x = -100; x <= 100; x++) {
      const px = canvas.width / 2 + x;
      const y = a * x * x + b * x + c;
      const py = canvas.height / 2 - y;
      x === -100 ? ctx.moveTo(px, py) : ctx.lineTo(px, py);
    }

    ctx.strokeStyle = "teal";
    ctx.lineWidth = 2;
    ctx.stroke();
  }, [a, b, c]);

  return <canvas ref={canvasRef} width={400} height={400} style={{ border: "1px solid gray" }} />;
};

Step 3: Dynamic Equation Switching

const EquationSelector = () => {
  const { dispatch } = useMath();

  const handleChange = () => {
    dispatch({
      type: "SET_EQUATION",
      payload: {
        id: "eq2",
        formula: "y = 2x² - 3x + 5",
        coefficients: [2, -3, 5]
      }
    });
  };

  return <button onClick={handleChange}>Switch Equationbutton>;
};

App Component

import { MathProvider } from "./MathContext";
import { EquationVisualizer } from "./EquationVisualizer";
import { EquationSelector } from "./EquationSelector";

export const App = () => (
  <MathProvider>
    <h1>