DEV Community

Cristian Sifuentes
Cristian Sifuentes

Posted on

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;
};
Enter fullscreen mode Exit fullscreen mode

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" }} />;
};
Enter fullscreen mode Exit fullscreen mode

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 Equation</button>;
};
Enter fullscreen mode Exit fullscreen mode

App Component

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

export const App = () => (
  <MathProvider>
    <h1>🧠 Equation Simulation</h1>
    <EquationSelector />
    <EquationVisualizer />
  </MathProvider>
);
Enter fullscreen mode Exit fullscreen mode

Key Concepts Illustrated

Hook Role in Simulation
useReducer Equation state machine
useContext Shared equation access across components
useLayoutEffect Canvas DOM render before paint
canvas + TS Visualize mathematical curves
TypeScript Precise modeling of equations

Conclusion

React’s advanced hooks offer the flexibility and structure needed to simulate real-world systems, including mathematical and scientific processes.

By combining useContext, useReducer, and useLayoutEffect, we:

  • Centralized state using reducers
  • Propagated updates globally with context
  • Ensured DOM synchronization before drawing equations

React isn’t just for UIs—it’s a powerful platform for modeling logic-heavy systems.

Next: Learn how to build a matrix visualizer using useMemo + useCallback + SVG.


Tags: react typescript useReducer useContext useLayoutEffect math canvas simulation frontend

Top comments (0)