Bộ chuyển đổi HTML sang JSX/React miễn phí
Chuyển đổi tự động HTML sang JSX tương thích React. Xử lý class→className, for→htmlFor, các đối tượng style, các trình xử lý sự kiện, các thẻ tự đóng và nhiều hơn nữa.
Đầu vào & đầu ra
Tùy chọn
Cách thức hoạt động
- Dán HTML: nhập một đoạn HTML chuẩn, divs, biểu mẫu, bảng hoặc các khối đầy đủ, vào khu vực nhập.
- Chọn các tùy chọn: kích hoạt việc bao bọc React Fragment và định dạng pretty-print theo nhu cầu.
- Lấy JSX ngay lập tức: bộ chuyển đổi tự động chuyển
class→className,for→htmlFor, các chuỗi style thành các đối tượng style, và đóng các thẻ tự đóng. - Sao chép vào dự án của bạn: dán đầu ra JSX trực tiếp vào các component React của bạn.
Tại sao sử dụng HTML → JSX?
Khi di chuyển các template HTML sang React, việc chuyển đổi thủ công dễ mắc lỗi. Quên một className đơn lẻ hoặc để lại một thẻ chưa đóng sẽ làm hỏng build. Bộ chuyển đổi này tự động xử lý tất cả các thay đổi cần thiết, bao gồm chuyển đổi các tên thuộc tính CSS như background-color sang camelCase backgroundColor trong các thuộc tính style, biến đổi các chuỗi trình xử lý sự kiện thành các tham chiếu hàm và đóng đúng các phần tử void. Điều này tăng tốc việc tạo prototype, các di chuyển mã và giúp các nhà phát triển không quen với các sự khác biệt cú pháp JSX.
Các chuyển đổi chính
- class → className, yêu cầu trong các component React
- for → htmlFor, cho các phần tử label
- các chuỗi style → các đối tượng, vd:
"color:red"→{color:'red'} - Các thẻ tự đóng,
<br>→<br /> - Bao bọc Fragment,
<>…</>bên ngoài tùy chọn
JSX thực sự là gì
JSX là viết tắt của «JavaScript XML». Đây là phần mở rộng cú pháp cho JavaScript do Jordan Walke tại Facebook phát minh vào năm 2013 trong thông báo React gốc tại JSConf US. JSX cho phép bạn viết markup kiểu XML trực tiếp bên trong code JavaScript, <div className="hello">World</div>: và một trình biên dịch (ngày nay hầu như luôn là Babel) biên dịch nó thành các lời gọi hàm thông thường: React.createElement('div', {className: 'hello'}, 'World'). Trình duyệt không bao giờ thấy JSX trực tiếp; những gì được gửi đi là JavaScript thông thường.
Động cơ ban đầu của Walke là các ngôn ngữ template (Mustache, Handlebars, directive cũ của Angular) là công dân hạng hai trong ngôn ngữ chủ, chúng không thể dùng vòng lặp, điều kiện hay biến của JavaScript một cách tự nhiên, nên mỗi ngôn ngữ lại phát minh lại cú pháp riêng của mình. JSX đảo ngược mối quan hệ đó: thay vì template đôi khi làm JavaScript, nó cho bạn JavaScript đôi khi làm markup. Thực tế là {condition && <Item />} là một biểu thức JS bình thường trả về một React element là ý tưởng cốt lõi.
Từ React 17 (tháng 10 năm 2020), JSX runtime tự động có nghĩa là bạn không còn phải import React from 'react' trong mọi file dùng JSX nữa, Babel tự động chèn các import runtime. JSX cũng được áp dụng vượt xa React: Preact, Solid, Qwik, Hono JSX, Million, Lit, và .tsx của TypeScript đều dùng cùng cú pháp. Bản thảo đặc tả JSX tại facebook.github.io/jsx được thiết kế cố tình không phụ thuộc framework.
Danh sách đầy đủ các khác biệt HTML→JSX
- Đổi tên từ khóa dành riêng.
class→className(vìclasslà từ khóa dành riêng trong JS).for→htmlFor(lý do tương tự,forlà từ khóa vòng lặp). Đây là hai cái mà mọi người đều bị vấp đầu tiên. - Tất cả thuộc tính khác dùng camelCase.
tabindex→tabIndex,readonly→readOnly,maxlength→maxLength,contenteditable→contentEditable. - Hai ngoại lệ quan trọng giữ dạng kebab-case. Thuộc tính
aria-*(aria-label,aria-hidden) và thuộc tínhdata-*(data-testid) giữ nguyên dạng HTML.xmlnscũng tương tự. - Thẻ tự đóng là bắt buộc cho các phần tử void:
<br>trở thành<br />,<img>trở thành<img />,<input>trở thành<input />. JSX nghiêm ngặt kiểu XML trong khi HTML thì rộng lượng. - Style nội tuyến nhận object, không phải chuỗi.
style="color: red; background-color: blue"trở thànhstyle={{ color: 'red', backgroundColor: 'blue' }}. Lưu ý ba điều: ngoặc nhọn đôi (một cho biểu thức JSX, một cho object literal), tên thuộc tính dùng camelCase, giá trị chuỗi được đặt trong dấu nháy. Giá trị pixel dạng số bỏ qua đơn vị:marginTop: 16, không phải'16px'. - Trình xử lý sự kiện dùng camelCase và nhận tham chiếu hàm.
onclick="handleClick()"trở thànhonClick={handleClick}: lưu ý không có dấu ngoặc đơn.onClick={handleClick()}sẽ gọi handleClick lúc kết xuất và gán giá trị trả về làm trình xử lý, điều này hầu như luôn là lỗi. - Comment dùng
{/* … */}bên trong JSX, không phải<!-- … -->. Cú pháp comment HTML không có ý nghĩa bên trong JSX. - Fragment bọc nhiều phần tử anh em. Một component phải trả về một root duy nhất, nên nhiều phần tử cấp cao nhất cần được bọc bởi
<>…</>(hoặc dạng dài hơn<React.Fragment>…</React.Fragment>). - Kết xuất có điều kiện dùng biểu thức JS.
{isVisible && <Item />}kết xuất item chỉ khi điều kiện là truthy;{condition ? <A /> : <B />}chọn một trong hai. - Dấu ngoặc nhọn trong văn bản cần thoát. Ký tự
{trong nội dung văn bản JSX được hiểu là bắt đầu một biểu thức. Dùng{'{'}hoặc thực thể HTML tương đương.
SVG, accessibility và những thứ khác
SVG hoạt động bên trong JSX với cùng quy tắc camelCase cho hầu hết thuộc tính, viewBox, strokeWidth, fillOpacity. Các ngoại lệ đáng chú ý: xlink:href dùng cách viết đặc biệt xlinkHref (nay không dùng nữa, ưu tiên dùng href thuần), và xmlns giữ nguyên. Thuộc tính accessibility tuân theo quy ước kebab-case riêng của ARIA theo ngoại lệ: aria-label, aria-describedby, role đều giữ nguyên.
Đối với CSS, object style nội tuyến của JSX là một tùy chọn. Hầu hết codebase production dùng một trong ba lựa chọn phong phú hơn: CSS Modules (tên class có phạm vi theo từng file được biên dịch bởi bundler), Tailwind CSS (utility class được truyền qua sạch sẽ thông qua className), hoặc các thư viện CSS-in-JS như styled-components, Emotion hay Vanilla Extract. Tailwind đã trở thành lựa chọn phổ biến nhất trong các dự án mới từ năm 2022; các class Tailwind không cần chuyển đổi gì khi chuyển HTML sang JSX, chúng được truyền qua như chuỗi className thông thường.
Những gotcha phổ biến khi chuyển đổi
- Trình xử lý sự kiện nội tuyến gọi trực tiếp hàm.
onclick="alert(1)"trong HTML thường trở thànhonClick={() => alert(1)}trong JSX, được bọc trong arrow function để alert kích hoạt khi click, không phải khi kết xuất. Bộ chuyển đổi đơn giản tạo raonClick={alert(1)}sẽ bật alert lúc kết xuất thay vì khi người dùng click. Bộ chuyển đổi này xử lý các trường hợp phổ biến nhưng vẫn nên kiểm tra kỹ đầu ra. - Comment HTML bị bỏ. Hầu hết bộ chuyển đổi JSX bỏ comment HTML thay vì dịch sang dạng
{/* */}, vì dạng sau chỉ hoạt động ở các vị trí cụ thể bên trong JSX. Thêm comment lại thủ công nơi bạn muốn. - Đổi tên thuộc tính SVG không phải lúc nào cũng được xử lý bởi bộ chuyển đổi tự động.
stroke-width,fill-rule,clip-path,text-anchorđều cần dạng camelCase, hãy kiểm tra kỹ đầu ra nếu bạn dán SVG từ bộ icon như Heroicons hay Lucide. - Thuộc tính boolean.
<input disabled>trong HTML trở thành<input disabled />trong JSX.<input disabled="false">trong HTML thực ra bị tắt (bất kỳ giá trị nào cũng bật nó), nhưng trong JSXdisabled={false}thì tắt đúng cách, ngữ nghĩa JSX hợp lý hơn HTML. - Thực thể HTML.
©hoạt động trong nội dung văn bản JSX nhưng dùng ký tự Unicode trực tiếp (©) được ưu tiên hơn. hoạt động tương tự. - Trường hợp
tabindex. Nên làtabIndex. Dễ quên vì giá trị thường là0hoặc-1và trông có vẻ là số, nhưng tên thuộc tính vẫn cần camelCase.
Khi nào bạn dùng công cụ này
- Di chuyển template server-rendered sang React. Dán một đoạn HTML từ site hiện có và nhận JSX là trường hợp sử dụng điển hình.
- Lấy icon, badge hoặc export từ design tool. Heroicons, Lucide, «Copy as SVG» của Figma đều cung cấp HTML/SVG thô cần qua bước đổi tên.
- Chuyển đổi snippet Tailwind UI / Flowbite / DaisyUI từ ví dụ HTML sang JSX cho dự án React. Các class Tailwind truyền qua không thay đổi; chỉ có các thuộc tính cấu trúc cần chuyển đổi.
- Hỗ trợ nhà phát triển biết HTML nhưng chưa biết JSX: thấy các quy tắc cơ học được áp dụng tự động nhanh hơn đọc danh sách các khác biệt.
- Tạo prototype nhanh khi bạn đã phác thảo markup trong HTML thuần cho mục đích phác họa và muốn đưa nó vào React component.
Đầu ra hoạt động với mọi consumer JSX, React, Preact, Solid, Qwik, Hono JSX, Million, template literal html của Lit (với các điều chỉnh nhỏ). Nó không hoạt động với React Native, vì React Native dùng các component primitive gốc như <View> và <Text> thay vì phần tử HTML.
Câu hỏi thêm
Sự khác biệt giữa JSX và HTML là gì?
HTML là ngôn ngữ đánh dấu mà trình duyệt phân tích trực tiếp. JSX là cú pháp biểu thức JavaScript biên dịch thành các lời gọi React.createElement, nó không bao giờ đến trình duyệt dưới dạng JSX. JSX trông nghiêm ngặt kiểu XML (mọi thẻ phải đóng, thuộc tính dùng camelCase) vì nó được phân tích như biểu thức JavaScript, không phải như HTML rộng lượng. Sự giống nhau về ngoại hình là có chủ đích nhưng ngữ nghĩa bên dưới khá khác nhau.
Tôi có còn cần import React trong mọi file JSX không?
Không còn nữa từ React 17 (tháng 10 năm 2020), phiên bản này giới thiệu JSX runtime tự động. Với nó, Babel tự động chèn các import runtime cần thiết, nên các file chỉ dùng JSX không cần import React from 'react' ở đầu file. Classic runtime vẫn có sẵn cho toolchain cũ hơn. Hầu hết dự án mới dùng automatic runtime.
Tôi có thể dùng JSX mà không có React không?
Có. JSX là cú pháp chung với bản thảo đặc tả tại facebook.github.io/jsx, và nhiều framework dùng nó: Preact, Solid, Qwik, Hono JSX, Million, Lit, và biến thể tagged-template htm. Các framework khác nhau về kết quả biên dịch của JSX (Preact dùng h(…), Solid biên dịch thành primitive phản ứng chi tiết, v.v.) nhưng cú pháp được chia sẻ.
Tại sao style nhận object thay vì chuỗi?
Vì cú pháp biểu thức JSX đã cung cấp ngoặc nhọn để nhúng giá trị JavaScript, và object literal là cách biểu diễn tự nhiên nhất trong JS cho một property bag. Object style cũng cho phép số (hầu hết tự động thêm px) và biểu thức JS, điều mà chuỗi không thể. Sự đánh đổi là cú pháp ngoặc đôi hơi kỳ cục style={{ … }}, ngoặc ngoài là «biểu thức JSX», ngoặc trong là object literal.
Có dữ liệu nào được gửi lên máy chủ không?
Không. Logic chuyển đổi là JavaScript thuần duyệt chuỗi HTML của bạn và viết lại thuộc tính, tất cả trong trình duyệt của bạn. HTML bạn dán không bao giờ rời khỏi trang, hữu ích khi di chuyển template nội bộ độc quyền hoặc markup component có endpoint API được nhúng vào.