Skip to content

เครื่องมือช่วยนักพัฒนาเว็บ React-Scan

Updated: at 06:30 PM (3 min read)

ในปัจจุบันขาเดฟคงน่าจะเคยได้ยินเครื่องมือที่ใช้ตรวจประสิทธิภาพของเว็บอยู่บ้าง เช่น

ซึ่งเครื่องมือแต่ละชิ้นก็จะมีหน้าที่คล้ายๆกัน ส่วนใหญ่จะมุ่งไปที่ Performance เป็นหลัก วันนี้เรามีอีกเครื่องมือมาแนะนำให้รู้จักกันอีกชิ้น นั่นก็คือ React Scan

Table of contents

Open Table of contents

Intro

วันนี้เราได้ไปเจอเครื่องมือใหม่ มีชื่อว่า React Scan มา ถือว่าเป็นอีกเครื่องมือไว้ใช้สแกนหน้าเว็บของเราว่ามีการ render ไปยังไงบ้าง เช่น Component Input render 200 ครั้ง 0.5ms หรือบ้างครั้งเราอาจจะเห็นว่ากดคลิกเดียว ทำไมถึง render ใหม่ทั้งหน้าทั้งที่ไม่มีความจำเป็นเลยซึ่งเครื่องมือนี้จะทำให้เราสามารถเห็นสิ่งเหล่านี้ในขณะที่เขียนโปรแกรมอยู่ได้เลย เราจึงสามารถวางแผนและจัดการได้ทันที

Installation & Setup

npm install react-scan

เมื่อลง package เสร็จแล้วให้ทำการแก้ไขไฟล์ main.tsx

// main.tsx
import { scan } from "react-scan"; // เพิ่มอันนี้
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";

// เพิ่มตรงนี้ด้วย
if (typeof window !== "undefined") {
  scan({
    enabled: true,
    log: true, // logs render info to console (default: false)
  });
}

หลังจากนั้นพอเราลองรันเดฟเซิฟเวอร์ก็จะพบหน้าตาแบบนี้

React scan setup complete

Scanning the site

ต่อมาเราจะมาลองใช้สแกนเว็บไซต์ของเราจากตัวอย่างโดยที่ลองเพิ่ม Input ไป 1 ชิ้นและเพิ่ม Component อีกอันไว้สำหรับแสดง Content

// Content.tsx
import React from "react";

export default function Content() {
  return <div>Here is content to check scan by react scan</div>;
}
// App.tsx
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";
import Content from "./Content";

function App() {
  const [count, setCount] = useState(0);
  const [input, setInput] = useState("");

  return (
    <>
      <div>
        <a href="https://vite.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <div style={{ marginBottom: "10px" }}>
          <input
            style={{ marginRight: "10px", minHeight: "34px" }}
            value={input}
            onChange={e => setInput(e.target.value)}
          />
        </div>
        <button onClick={() => setCount(count => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
      <Content />
      <Content />
      <Content />
      <Content />
    </>
  );
}

export default App;

คราวนี้เรามาลองพิมพ์ค่าลง Input หรือคลิกที่ปุ่ม Counter จะเห็นได้ว่า Content component ถูก Rerender ทั้งหมดซึ่งในความเป็นจริงถ้าไม่ได้เกี่ยวข้องกันโดยตรงก็ไม่ควรจะต้อง rerender ด้วยซ้ำ

Rerender Example

Simple Optimize

จากโค้ดข้างบนเราลองทำการแยก Component ที่ต้องใช้ State ออกมา

// Counter.tsx
import React, { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count => count + 1)}>
      count is {count}
    </button>
  );
}
// Input.tsx
import React, { useState } from "react";

export default function Input() {
  const [input, setInput] = useState("");

  return (
    <div style={{ marginBottom: "10px" }}>
      <input
        style={{ marginRight: "10px", minHeight: "34px" }}
        value={input}
        onChange={e => setInput(e.target.value)}
      />
    </div>
  );
}
// App.tsx
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";
import Content from "./Content";
import Counter from "./Counter";
import Input from "./Input";

function App() {
  // const [count, setCount] = useState(0);
  // const [input, setInput] = useState("");

  return (
    <>
      <div>
        <a href="https://vite.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <Input />
        <Counter />
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
      <Content />
      <Content />
      <Content />
      <Content />
    </>
  );
}

export default App;

ต่อมาเราลองไปพิมพ์ค่าใน input หรือกดปุ่มจาก counter จะเห็นได้เลยว่า component อื่นๆไม่ได้ถูก render ใหม่ที่เป็นแบบนี้เพราะว่าตัว state ไม่ได้อยู่ใน App.tsx แล้วแต่ไปอยู่ใน component ต่างๆแทน

Simple Optimize

Chrome Extension (Develop mode)

ตอนนี้มีให้ทาง React scan ได้ทำตัว Chrome Extension แบบ Developer mode กันอยู่เมื่อสมบูรณ์ถึงจะปล่อยเป็นตัวตาม ส่วนวิธีการเปิดใช้งานดูเพิ่มเติม ที่นี่

Scanning any site

นอกจากสแกนในเว็บเราได้แล้วยังสามารถสแกนเว็บอื่นๆได้อีกด้วย เช่น Github

npx react-scan@latest https://github.com
# you can technically scan ANY website on the web:
# npx react-scan@latest https://react.dev

ผลลัพธ์ที่ได้คือ

Github Example

นอกจากนี้เรายังสามารถ Inspect Github จาก Element/Componet ได้อีกด้วย

Github Example

Conclusion from writer

หลังจากที่ได้ลองใช้มา 1 อาทิตย์ก็รู้สึกว่าดีมากในแง่ของการได้เห็นการ render และกดดูตามแต่ละ component ส่วนตัวคิดว่าน่าจะใช้งานต่อไป แถมทางผู้พัฒนาก็อยากจะทำไปต่อในส่วนของ React Native กับ Chrome Extension อีกด้วย


Previous Post
Tailwind CSS Framework (Utility first)
Next Post
Abort Controller มากกว่าแค่ Cancel Data Fetching