Tìm hiểu về $$typeof Property trong React

<marquee bgcolor="#000">Chào buổi sáng</marquee> React.createElement(/* type */'marquee',/* props */{ bgcolor:'#000'},/* children */'Hi') Bạn thấy 2 đoạn code trên có liên quan tí nào không ? Thực tế thì có đó, đoạn code đầu tiên sẽ được babel biên dịch ra giống như đoạn code thứ 2. Và function trên sẽ trả về cho chúng ta

<marquee bgcolor="#000">Chào buổi sáng</marquee>
React.createElement(/* type */'marquee',/* props */{ bgcolor:'#000'},/* children */'Hi')

Bạn thấy 2 đoạn code trên có liên quan tí nào không ?
Thực tế thì có đó, đoạn code đầu tiên sẽ được babel biên dịch ra giống như đoạn code thứ 2. Và function trên sẽ trả về cho chúng ta một object, và nó được gọi là React element, nó cho biết tiếp theo React sẽ cần làm gì

{
    type:'marquee',
    props:{
        bgcolor:'#000',
        children:'Hi',},
    key:null,
    ref:null,
    $$typeof: Symbol.for('react.element'),// 🧐}

Mọi thứ trông rất bình thường, nhưng có một thứ mà ta cần phải đặt dấu chấm hỏi ở đây, $$typeof là cái gì và tại sao lại có kiểu Symbol ?
Tò mò thì mình tìm hiểu về nó thôi, thực tế thì nếu chỉ sử dụng React thì nó cũng không ảnh hưởng tới việc coding của chúng ta.
Lúc còn là newbie mình thường sử dụng như thế này để chèn HTML bằng javascript.

const messageEl = document.getElementById('message');
messageEl.innerHTML ='<p>'+ message.text +'</p>';

Sau này khi đi thực tập, mình mới biết làm điều này nguy hiểm tới chừng nào. Thử thay thế tạm đoạn code này vào message.text

  // Thậm chí viblo còn không cho phép mình viết trực tiếp :))
  <imgsrcnerror=" stealYourPassword() ">

Bumpppp, bạn có nguy cơ bị XSS. Một anh senior đã hướng dẫn mình sử dụng tránh bị XSS đó là:

  • Sử dụng document.createTextNode()
  • Sử dụng textContent
  • Bỏ hết ký tự <> đi
    Với React thì mọi thử đơn giản đã là mặc định.
<div>{message.text}</div>

Hoặc có thể sử dụng cách như thế này.

dangerouslySetInnerHTML={{ __html: message.text }}

Nhưng mà tới đây vẫn chưa đủ, vẫn còn rất nhiều cách để XSS bằng HTMLDOM
Ví dụ: <a href={user.website}> hay <div {...userData}> cũng nguy hiểm
Với cách viết này

<div>{message.text}</div>

vẫn chưa đủ an toàn một số trường hợp, một React element được khởi tạo bằng React.createElement() có dạng object như thế này

{
  type:'marquee',
  props:{
    bgcolor:'#ffa7c4',
    children:'hi',},
  key:null,
  ref:null,
  $$typeof: Symbol.for('react.element'),}

Nếu chúng ta lưu trữ nó ở trên server như một JSON, với React 0.13 đây là điểm bị lợi dụng để XSS

// JSON được lưu trên serverlet expectedTextButGotJSON ={
  type:'div',
  props:{
    dangerouslySetInnerHTML:{
      __html:'/* đưa đoạn XSS vào đây */'},},// ...};let message ={ text: expectedTextButGotJSON };// Nguy hiểm<p>{message.text}</p>

Phiên bản 0.14 React hỗ trợ xử lý con bug này bằng cách thêm đánh dấu đây chính hiệu là React element bằng Symbol

{
  type:'marquee',
  props:{
    bgcolor:'#ffa7c4',
    children:'hi',},
  key:null,
  ref:null,
  $$typeof: Symbol.for('react.element'),}

Tại vì, trong JSON chúng ta không thể chèn một Symbol (khi stringyfy Symbol sẽ trở thành undefined), thậm chí Back end có cho phép return JSON thay vì text thì cũng không thể đưa Symbol.for('react.element') vào trong JSON đó.

Điều tuyệt vời nữa, là Symbol.for() thì scope ở mức global giữa các môi trường như iframe, worker. Nghĩa là sử dụng component qua lại giữa các môi trường khác nhau cũng không bị ảnh hưởng.

Nhưng có một điều, trình duyệt không hỗ trợ Symbol thì sao?
React sẽ vẫn thêm vào property$$typeof, nhưng với giá trị 0xeac7, tại sao là 0xeac7? Tại React team thấy nhìn nó giống chữ "React" =))

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ