Hướng dẫn cài đăt và cấu hình kafka

  

1 Giới thiệu

1.1 Mục đích tài liệu

2 Thủ tục .

2.1 Chuẩn bị cài đặt

2.2 Cài đặt java.

2.3 Cài đặt và cấu hình Zookeeper.

2.4 Cài đặt, tạo service và cấu hình cho kafka.



  1. Giới thiệu

    1. Mục đích tài liệu

  • Tài liệu này mô tả hướng dẫn cài đặt và cấu hình kafka.


  1. Thủ tục .

  1. Chuẩn bị cài đặt 

  • Thực hiện login hệ thống bằng tài khoản root sử dụng lệnh sau :

sudo su

Sau đó nhập mật khẩu để thực hiện việc login.

  • Thực hiện update (nếu có thể) sử dụng 2 lệnh sau:

sudo apt-get update -y

sudo apt-get upgrade -y

  1. Cài đặt java.

Bước 1: Thực hiện bổ sung  repository lệnh sau:


sudo add-apt-repository -y ppa:webupd8team/java


Sauk hi thực hiện lệnh trên sẽ nhìn thấy màn hình như sau: 

gpg: keyring `/tmp/tmpkjrm4mnm/secring.gpg' created

gpg: keyring `/tmp/tmpkjrm4mnm/pubring.gpg' created

gpg: requesting key EEA14886 from hkp server keyserver.ubuntu.com

gpg: /tmp/tmpkjrm4mnm/trustdb.gpg: trustdb created

gpg: key EEA14886: public key "Launchpad VLC" imported

gpg: no ultimately trusted keys found

gpg: Total number processed: 1

gpg:               imported: 1  (RSA: 1)

OK


Bước 2: Thực hiện update cho repository mới sử dụng lệnh sau:

sudo apt-get update


Bước 3: Thực hiện lệnh sau để cài đặt JDK 8.


 

sudo apt-get install oracle-java8-installer -y


Sau khi cài đặt, cần kiểm tra việc cài đặt có thành công hay không. Sử dụng lệnh để kiểm tra version .


sudo java -version

Nếu thành công sẽ hiện ra màn hình như sau: 

java version "1.8.0_66"

Java(TM) SE Runtime Environment (build 1.8.0_66-b17)

Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)

  1. Cài đặt và cấu hình Zookeeper.

Bước 1: Thực hiện lệnh sau để cài đặt zookeeper:

sudo apt-get install zookeeperd

Để kiểm tra việc cài đặt dùng lênh sau:

netstat -ant | grep :2181


Nếu thành công sẽ hiện ra màn hình như sau: 

tcp6       0      0 :::2181                 :::*                    LISTEN

 


Bước 2: Thực hiện cấu hình tăng số lượng connection đến zookeeper sử dụng lệnh:

echo "maxClientCnxns=500" >> /etc/zookeeper/conf/zoo.cfg

Bước 3: Thực hiện restart lại service sử dụng lệnh:

service zookeeper restart

Có thể xem log của zookeeper sử dụng lệnh:

tail -f /var/log/zookeeper/zookeeper.log 

  1. Cài đặt, tạo service và cấu hình cho kafka.

Bước 1: Thực hiện download bản cài đặt của kafka sử dụng lệnh sau:

wget http://www-eu.apache.org/dist/kafka/1.0.0/kafka_2.12-1.0.0.tgz

Bước 2: Thực hiện giải nén và copy tới thư mục opt sử dụng thứ tự các lệnh:

cp kafka_2.12-1.0.0.tgz /opt/

cd /opt/

tar xvzf kafka_2.12-1.0.0.tgz

mv kafka_2.12-1.0.0 kafka

Bước 2: Thực hiện tạo service cho kafka:

     +)Tạo user kafka sử dụng lệnh:

sudo useradd kafka -m

     +)Tạo file kafka.service sử dụng lệnh:

vim /etc/systemd/system/kafka.service

Với nội dung như sau:

[Unit]

Description=High-available, distributed message broker

After=network.target

[Service]

User=kafka

ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties

[Install]

WantedBy=multi-user.target





          +) Thực hiện thứ tự các lênh:

          sudo systemctl daemon-reload

             sudo systemctl enable kafka.service

             sudo systemctl start kafka.service

          +) Để kiểm tra việc tạo service sử dụng lệnh sau:

sudo systemctl status kafka

Màn hình sẽ hiện ra như sau:

Bước 3: Thực hiện thêm tham số cấu hình cho kafka:

Mở file ở đường dẫn sử dụng lệnh sau: 

   vim /opt/kafka/config/server.properties

Thêm vào dòng sau:

auto.create.topics.enable=true

 

Thực hiện restart dịch vụ để thay đổi có tác dụng sử dụng lệnh sau:

sudo systemctl restart kafka



Object oriented programming - JAVA







Advanced OOP with Java

Front-End Fundamental

FRONT END DEVELOPER

Khi ta bàn đến frontend, nghĩa là ta đụng đến phần web mà ta có thế trông thấy được và tương tác với nó, nghiã là phiá web browser. Frontend thường gồm 2 phần:  web design  và  frontend web development .
Trong thời gian qua, khi ai đó bàn đến triển khai  thì thường người ta nói đến backend, nhưng những năm gần đây người ta cần phân biệt giữa các designers làm việc chuyên về Photoshop với các designer có thể lo coding (mã hóa) theo HTML và CSS, hoặc designers làm việc với Javascript và jQuery.
Do đó, ngày nay khi ta bàn đến "web design" thì thực sự ta sẽ nói đến những ai làm việc với Photoshop và Fireworks, và  kể cả những ai lo coding sữ dụng HTML, CSS, Javascript hoặc jQuery (bạn đế ý jQuery là một thư viện trọn vẹn của Javascript).
Mọi việc mà bạn thấy khi dùng web là sự phối hợp của HTML, CSS và Javascript, tất cả được kiểm soát bởi bộ browser trên máy tính của bạn. Đây là bao gồm những cái như font, drop-down menus, buttons, transitions, sliders, contact forms, v.v..


HTML, CSS Fundamental




Javascript Fundamental




Jquery, Ajax Fundamental

ĐỊNH NGHĨA WEB BROWSER VÀ ỨNG DỤNG WEB
Theo quan điểm kỹ thuật, mạng web là một môi trường được lập trình cao cấp và phức tạp nhất cho phép thích ứng khối lượng lớn những ứng dụng kích cỡ khác nhau đối với hằng triệu người sữ dụng toàn cầu. Trong một website tiên tiến hiện đại, thì 2 cấu thành quan trọng nhất là (1) những bộ trình duyệt (web browsers) linh động uyển chuyển; (2) và những ứng dụng mạng web. Cả 2 cấu thành này đều có sẵn và miễn phí cho tất cả mọi người trên thế giới.
Web browser là những ứng dụng phần mềm cho phép người sữ dụng tìm đọc lại dữ liệu và tương tác với nội dung nằm trên các trang web thuộc website nào đó. Giờ đây các trang web tiên tiến thường có nội dung động sặc tính cá nhân, nên được kéo xuống theo sắp đặt của chủ trang web. Ngoài ra, các trang web còn có thể cho chạy những kịch bản (script) phía client cho phép thay đổi internet browser thành một giao diện làm việc với những ứng dụng, chẵng hạn web Mail cũng như phần mềm bản đồ tương tác (TD Yahoo Mail, Google Maps).
Điều quan trọng nhất, là các website tiên tiến giờ đây cho phép thu thập dữ liệu, xữ lý và cất trữ các dữ liệu này, cũng như truyền đi dữ liệu nhạy cãm của khách hàng (chẵng hạn các dữ liệu chi tiết cá nhân, thẽ tín dụng, thông tin BHXH,  v.v..) để sữ dụng ngay liền hoặc về sau. Và việc này được thực hiện thông qua cá ứng dụng mạng. Những tính năng (feature) chẵng hạn webmail, login pages, các biễu mẫu yêu cầu hỗ trợ hoặc sản phẩm, shopping cart và các hệ thống quản lý nội dung, hình thành những website tiên tiến và cung cấp cho ngành kinh doanh những phương tiện cần thiết để liên lạc với khách hàng hiện tại và tiềm năng. Đây được xem như là những thí dụ phổ biến thông thường của các ứng dụng mạng.
Do đó, các ứng dụng web là những chương trình phần mềm máy tính cho phép khách tham quan website yêu cầu đọc lại dữ liệu đi đi về về với database trên internet thông qua web browser quen thuộc của mình. Lúc này dữ liệu sẽ được trình bày cho người sữ dụng trong lòng web browser của người sữ dụng khi thông tin được kết sinh kiểu động (theo một dạng thức cụ thể, nghĩa là theo HTML5 sử dụng CSS) bởi ứng dụng web thông qua một web server
Nếu nói theo giọng điệu kỹ thuật, thì các ứng dụng web yêu cầu phía server cung cấp nội dung dữ liệu (thường là bộ trữ database chứa nội dung dữ liệu của khách hàng) đồng thời kết sinh (generate) một cách động các tài liệu web cần thiết đối với khách hàng, là người đang lướt trên website. Các tài liệu tin học sẽ được kết sinh dưới dạng thức chuẫn cho phép hỗ trợ bởi tất cả các browser (nghĩa là HTML hoặc XHTML). Ngôn ngữ lập trình JavaScript là một hình thức ngôn ngữ kịch bản phía client cho phép kết sinh những phần tữ động trên mỗi trang web (nghĩa là một hình ảnh sẽ thay đỗi một khi con chuột người sữ dụng rề rề trên hình ảnh). Nói tóm lại, web browser là thành phần chủ chốt, nghĩa là nó suy diễn và cho chạy tất cả các kịch bản, trong khi cho biễu thị tất cả các trang mạng được yêu cầu kèm theo nội dung. Web browser là khách hàng phỗ biến đối với bất cứ ứng dụng mạng nào.
Một lợi điểm khá quan trọng khác trong việc xây dựng và duy trì bất cứ ứng dụng web này là chúng thực hiện chức năng không cần biết phía client có hệ điều hành và browser nào. Các ứng dụng web sẽ nhanh chóng được triễn khai bất cứ nơi nào không phí tổn cũng như không cần yêu cầu cài đặt gì từ phía người sữ dụng.
Khi số doanh nghiệp làm ăn trên mạng ngày càng tăng thì việc sữ dụng các ứng dụng web cũng tăng theo cũng như các công nghệ ăn theo cũng tiếp tục tăng theo. Ngoài ra, từ khi việc intranet và extranet được chấp thuận, thì các ứng dụng web bị thu mình sau bất cứ hạ tầng cơ sở thông tin liên lạc nào của tổ chức, nên làm nới rộng phạm trù và khả năng phức tạp kỹ thuật. 
Các ứng dụng mạng có thể có sẵn trên thị trường hoặc được tạo ngay tại cơ sở.
CÁC ỨNG DỤNG MẠNG HOẠT ĐỘNG THẾ NÀO?

Hình 1 dưới đây cho thấy chi tiết mô hình ứng dụng mạng gồm 3 lớp (layer). Lớp 1 thường gồm một web browser, hoặc còn gọi là giao diện người sữ dụng (UI - user interface). Lớp 2, Web Application Server, là công cụ kỹ thuật kết sinh nội dung động, chẵng hạn Java servlet (JSP) hoặc Active Server Pages (ASP). Còn lớp 3, Database server, là database chứa nội dung (content, nghĩa là news) và dữ liệu của khách hàng (chẵng hạn : username và password, mã BHXH và chi tiết thẽ tín dụng).


Hình 1:

What is a Web App?


'
Hình 2 dưới đây cho thấy truy vấn (request) ban đầu kích hoạt bởi người sữ dụng thông qua web browser trên Internet gởi cho server của ứng dụng mạng. Lúc này, ứng dụng web sẽ truy cập database nằm trên server để cho thực hiện công tác truy xuất bằng cách cập nhật và tìm đọc thông tin được trữ trên database. Sau đó, thì ứng dụng mạng liền trình bày thông tin cho người sữ dụng thông qua web browser phía client.
Hình 2:
How Web Apps Access Database Servers

CÁC VẤN ĐỀ VỀ WEB SECURITY

Mặc dù những lợi điểm có được, các ứng dụng web cũng đem lại một số vấn đề liên quan đến an toàn mạng do đầy lỗi lập trình không thích ứng. Yếu kém quan trọng hoặc tính tổn thương cho phép các tay hacker chui trực tiếp vào các điểm truy cập trực tiếp và công công và những hệ thống  databases đế ăn cắp các dữ liệu nhạy cãm. Nhiều  databases này chứa nhiều thông tin qúy giá, nhạy cãm ( td : các chi tiết cá nhân và kinh tế tài chính) thường xuyên làm mồi cho hacker. Hacker giờ đây thích truy cập vào những dữ liệu nhạy cãm nằm trên các  database server vì thu khá tiền bằng cách bán dữ liệu nhạy cãm.
Dựa theo  framework được mô tả ở trên, ta có thể thấy một hacker thông minh và sáng tạo một chút có thể thâm nhập nhanh lấy đi dễ dàng dữ liệu nằm trên database và may mắn một chút với sự lơ đễnh và sai lầm của nhân viên điều hảnh và tin học, đưa đến sự tổn thương của các ứng dụng web.
Như đã nói, các website thường thuộc vào các database phía server để cung cấp thông tin cho khách hàng trên browser phia client. Do đó, nếu ứng dụng  web không an toàn thì như vậy toàn bộ dữ liệu nhạy cãm trên database sẽ bị nguy khốn.
Thí dụ một vài hackers có thể "bơm" đoạn mã xấu vào trong lòng những ứng dụng web bị tổn thương lừa khách hàng rồi chuyễn đoạn mã vào những  phishing sites. Phishing là  việc xây dựng những hệ thống lừa đảo nhằm đánh cắp các thông tin nhạy cảm, như tên đăng nhập, mật khẩu hay thông tin về các loại thẻ tín dụng của người dùng. Kỹ thuật phishing này được gọi là  Cross-Site Scripting  và có thể được sữ dụng thông qua các web servers và database engine bản thân không bị tổn thương. Những nghiên cứu mới đây cho thấy 75% các tấn công tin học thường xãy ra ở cấp ứng dụng web.
Tuy nhiên, kỹ thuật  phishing theo kiểu  cross-site scripting giờ đây không có tác dụng, trừ khi người lập trình Web non nớt, vướng vào sai lầm cũ.
How Hackers Attack Web Applications
  • Websites và các ứng dụng web phãi hiện điện 24 giờ một ngày, 7 ngày một tuần, để cung cấp dịch vụ được yêu cầu cho khách hàng, nhân viên, nhà cung cấp và  các đối tượng khác. 
  • Firewalls (bức tường lữa) và SSL không cung cấp bất cứ bảo vệ trước web application hacking, đơn giản là vì việc truy cấp website phãi là công cộng - Tất cả các hệ thống database tiên tiến (thí dụ: Microsoft SQL Server, Oracle và MySQL) có thể được truy cập thông qua các specific ports (td: port 80 và 443) và bất cứ ai cũng có thể cố gắng kết nối thẵng vào database một cách hữu hiệu bằng cách bỏ qua các cơ chế an ninh mà hệ điều hành đang sữ dụng. Các cổng (port) này tiếp tục mở cho phép liên lạc với giao thông hợp pháp, và như vậy tạo nên sự bất ổn lớn nhất.
  • Các ứng dụng Web applications thường xuyên truy cập trực tiếp vào dữ liệu backend chẵng hạn databases data, như vậy kiểm soát dữ liệu đáng giá và khó lòng bảo đãm an ninh. Còn những ai không thể truy cập thì sẽ có một dạng thức kịch bản nào đó cho phép thu thập và truyền lưu dữ liệu. Nếu một tay hacker biết được điễm yếu của kịch bản nào đó, thì nó có thể chuyễn hướng dễ đàng về một nơi khác và cướp đoạt bất chính các chi tiết cá nhân của khách hàng. 
  • Phần lớn các ứng dụng web là do khách hàng tự tạo (được gọi là custom-made) nên do đó trắc nghiệm yếu kém so với phần mềm mua trên thị trường (được gọi là off-the-shelf software). Do vậy, các ứng dụng nhà làm dễ bị hacker tấn công. 
Tóm lại, bạn phãi đặt câu hỏi : “Những phần nào trên một website mà ta cho là an toàn sẽ bị hacker tấn công?" và "dữ liệu nào ta có thể đưa vào một ứng dụng gây ra viêc làm đáng ra không nên làm?". 

Reactjs Style

Mục lục

  1. Những luật cơ bản
  2. So sánh Class vs React.createClass vs stateless
  3. Mixins
  4. Đặt tên
  5. Khai báo
  6. Căn chỉnh mã nguồn
  7. Dấu nháy đơn và nháy kép
  8. Khoảng trắng
  9. Props
  10. Refs
  11. Dấu ngoặc đơn
  12. Thẻ
  13. Phương thức
  14. Cách sắp xếp hàm
  15. Thuộc tính isMounted

Những luật cơ bản

  • Chỉ chứa một React Component trong 1 file.
  • Tuy nhiên, những component có khả năng sử dụng lại(Stateless Component, hoặc Pure Components) có thể viết chung một file. eslint: react/no-multi-comp.
  • Luôn luôn sử dụng cú pháp JSX.  - Không sử dụng React.createElement chung với cú pháp JSX.

So sánh class vs React.createClass vs stateless

  • Nếu Component có state hoặc refs, nên sử dụng class extends React.Component thay vì React.createClass. eslint: react/prefer-es6-class react/prefer-stateless-function

    // tệ
    const Listing = React.createClass({
      // ...
      render() {
        return <div>{this.state.hello}</div>;
      }
    });
    
    // tốt
    class Listing extends React.Component {
      // ...
      render() {
        return <div>{this.state.hello}</div>;
      }
    }

    Và nếu trong Component không có state hoặc refs, nên sử dụng khai báo hàm (không phải arrow function) thay vì class:

    // tệ
    class Listing extends React.Component {
      render() {
        return <div>{this.props.hello}</div>;
      }
    }
    
    // tệ (dựa vào tên hàm để suy luận thì rất đau đầu)
    const Listing = ({ hello }) => (
      <div>{hello}</div>
    );
    
    // tốt
    function Listing({ hello }) {
      return <div>{hello}</div>;
    }

Mixins

Mixins tạo ra các implicit dependencies(phụ thuộc ngầm), gây ra xung đột tên và tăng độ phức tạp. Có thể thay thế mixins bằng components, higher-order components, hoặc các utility modules(gói tiện ích).

Đặt tên

  • Phần mở rộng(extensions): Sử dụng phần mở rộng .jsx cho React Components.

  • Tên file: Sử dụng chuẩn PascalCase cho tên file. Ví dụ: ReservationCard.jsx.

  • Tên tham chiếu(Reference Naming): Sử dụng PascalCase cho React components và dùng camelCase cho các đối tượng(instances) của chúng. eslint: react/jsx-pascal-case

    // tệ
    import reservationCard from './ReservationCard';
    
    // tốt
    import ReservationCard from './ReservationCard';
    
    // tệ
    const ReservationItem = <ReservationCard />;
    
    // tốt
    const reservationItem = <ReservationCard />;
  • Đặt tên Component: Sử dụng tên file trùng với tên component. Ví dụ: ReservationCard.jsx nên có tên tham chiếu là ReservationCard. Tuy nhiên, đối với các component gốc của một thư mục, hãy sử dụng index.jsx làm tên file và sử dụng tên thư mục làm tên component:

    // tệ
    import Footer from './Footer/Footer';
    
    // tệ
    import Footer from './Footer/index';
    
    // tốt
    import Footer from './Footer';
  • Đặt tên Higher-order Component: Sử dụng sự kết hợp của Higher-order component và tên của component đuợc truyền như displayName(tên hiển thị) trên component đuợc tạo ra. Ví dụ component bậc cao withFoo(), khi truyền một component Bar sẽ tạo ra một component với displayName của withFoo(Bar).

    Tại sao? Vì displayName của component có thể đuợc sử dụng bởi những công cụ phát triển hoặc trong các thông báo lỗi, và có một giá trị mà thể hiện rõ mối quan hệ này sẽ giúp chúng hiểu rõ chuyện gì đang xảy ra.

    // tệ
    export default function withFoo(WrappedComponent) {
      return function WithFoo(props) {
        return <WrappedComponent {...props} foo />;
      }
    }
    
    // tốt
    export default function withFoo(WrappedComponent) {
      function WithFoo(props) {
        return <WrappedComponent {...props} foo />;
      }
    
      const wrappedComponentName = WrappedComponent.displayName
        || WrappedComponent.name
        || 'Component';
    
      WithFoo.displayName = `withFoo(${wrappedComponentName})`;
      return WithFoo;
    }
  • Đặt tên Props: Tránh sử dụng tên props của DOM Component cho mục đích khác.

    Tại sao? Mọi nguời mong đợi props như style và className có ý nghĩa riêng. Việc thay đổi mục đích sử dụng của API gốc làm cho mã khó đọc và khó bảo trì hơn, thậm chí có thể gây ra lỗi.

    // tệ
    <MyComponent style="fancy" />
    
    // tệ
    <MyComponent className="fancy" />
    
    // tốt
    <MyComponent variant="fancy" />

Khai báo

  • Không nên sử dụng displayName để đặt tên cho các Components. Thay vào đó, đặt tên cho các Components bằng references(tham chiếu).

    // tệ
    export default React.createClass({
      displayName: 'ReservationCard',
      // một số thứ khác
    });
    
    // tốt
    export default class ReservationCard extends React.Component {
    }

Căn chỉnh mã nguồn

  • Căn chỉnh cho cú pháp JSX. eslint: react/jsx-closing-bracket-location react/jsx-closing-tag-location

    // tệ
    <Foo superLongParam="bar"
         anotherSuperLongParam="baz" />
    
    // tốt
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    />
    
    // Nếu props phù hợp trong một dòng thì giữ nó trên cùng một dòng
    <Foo bar="bar" />
    
    // Component con được thụt lề bình thường
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    >
      <Quux />
    </Foo>

Dấu nháy đơn và nháy kép

  • Luôn luôn sử dụng dấu ngoặc kép (") cho các thuộc tính JSX, nhưng dấu nháy đơn (') cho tất cả các JS khác. Eslint: jsx-quotes

    Tại sao? Vì các thuộc tính HTML thông thường thường sử dụng dấu ngoặc kép thay vì đơn, vì vậy thuộc tính JSX cũng như thế.

    // tệ
    <Foo bar='bar' />
    
    // tốt
    <Foo bar="bar" />
    
    // tệ
    <Foo style={{ left: "20px" }} />
    
    // tốt
    <Foo style={{ left: '20px' }} />

Khoảng trắng

  • Luôn luôn có duy nhất một kí tự space(khoảng trắng) trong thẻ tự đóng. eslint: no-multi-spacesreact/jsx-tag-spacing

    // tệ
    <Foo/>
    
    // rất tệ
    <Foo                 />
    
    // tệ
    <Foo
    />
    
    // tốt
    <Foo />
  • Không dùng khoảng trắng giữa giá trị bên trong ngoặc nhọn. eslint: react/jsx-curly-spacing

    // tệ
    <Foo bar={ baz } />
    
    // tốt 
    <Foo bar={baz} />

Props

  • Luôn luôn sử dụng camelCase khi đặt tên prop (camelCase : viết hoa chữa cái đầu của các từ , từ đầu tiên của cụm thì viết thường)

    // tệ
    <Foo
      UserName="hello"
      phone_number={12345678}
    />
    
    // tốt
    <Foo
      userName="hello"
      phoneNumber={12345678}
    />
  • Bỏ giá trị của prop khi nó thực sự rõ ràng là true. eslint: react/jsx-boolean-value

    // tệ
    <Foo
      hidden={true}
    />
    
    // tốt
    <Foo
      hidden
    />
    
    // tốt
    <Foo hidden />
  • Luôn luôn sử dụng prop alt trong thẻ <img>. Nếu giá trị của thẻ là NULL , alt có thể là một chuỗi rỗng hoặc <img> phải có thuộc tính role="presentation". eslint: jsx-a11y/alt-text

    // tệ
    <img src="hello.jpg" />
    
    // tốt
    <img src="hello.jpg" alt="Me waving hello" />
    
    // tốt
    <img src="hello.jpg" alt="" />
    
    // tốt
    <img src="hello.jpg" role="presentation" />
  • Không dùng các từ "image", "photo", hoặc "picture" trong <img> alt props. eslint: jsx-a11y/img-redundant-alt

    Tại sao? Screenreaders đã tự hiểu img elements là image(ảnh), vì vậy không cần khai báo thông tin này trong alt

    // tệ
    <img src="hello.jpg" alt="Picture of me waving hello" />
    
    // tốt
    <img src="hello.jpg" alt="Me waving hello" />
  • Chỉ sử dụng ARIA roles. eslint: jsx-a11y/aria-role hợp lệ, và không trừu tượng. jsx-a11y/aria-role

    // tệ - không phải ARIA roles
    <div role="datepicker" />
    
    //tệ- ARIA roles trừu tượng
    <div role="range" />
    
    // tốt
    <div role="button" />
  • Không dùng accessKey trong các elements. eslint: jsx-a11y/no-access-key

    Tại sao ? Sự mâu thuẫn giữa phím tắt và các lệnh bàn phím được những người dùng screenreaders sử dụng làm phức tạp hóa khả năng tiếp cận.

    // tệ
    <div accessKey="h" />
    
    // tốt
    <div />
  • Tránh dùng chỉ số của mảng(index) cho thuộc tính key, nên sử dụng một unique ID(định danh duy nhất). (why?)

    // tệ
    {todos.map((todo, index) =>
    <Todo
      {...todo}
      key={index}
    />
    )}
    
    // tốt
    {todos.map(todo => (
    <Todo
      {...todo}
      key={todo.id}
    />
    ))}
  • Luôn xác định rõ ràng các defaultProp(thuộc tính mặc định) cho tất cả non-required props(thuộc tính không bắt buộc).

    Tại sao? propTypes được coi như tài liệu, và cung cấp defaultProps , nghĩa là người đọc mã nguồn của bạn không cần phải đoán quá nhiều. Ngoài ra, nó có thể bỏ qua một số kiểm tra kiểu(type checking).

    // tệ
    function SFC({ foo, bar, children }) {
      return <div>{foo}{bar}{children}</div>;
    }
    SFC.propTypes = {
      foo: PropTypes.number.isRequired,
      bar: PropTypes.string,
      children: PropTypes.node,
    };
    
    // tốt
    function SFC({ foo, bar, children }) {
      return <div>{foo}{bar}{children}</div>;
    }
    SFC.propTypes = {
      foo: PropTypes.number.isRequired,
      bar: PropTypes.string,
      children: PropTypes.node,
    };
    SFC.defaultProps = {
      bar: '',
      children: null,
    };
  • Hạn chế lạm dụng toán tử spread cho việc truyền props

Tại sao? Vì bạn có khả năng truyền props không cần thiết xuống Components. Và với React v15.6.1 trờ lên, bạn cần chuyển các thuộc tính không hợp lệ của HTML sang DOM.

Ngoại lệ:

  • HOCs có thể truyền thẳng props xuống và khai báo propTypes

    function HOC(WrappedComponent) {
    return class Proxy extends React.Component {
      Proxy.propTypes = {
        text: PropTypes.string,
        isLoading: PropTypes.bool
      };
    
      render() {
        return <WrappedComponent {...this.props} />
      }
    }
    }
  • Sử dụng toán tử spread đối với prop được khai báo rõ ràng. Điều này có thể đặc biệt hữu ích khi test các React component với cấu trúc beforeEach của Mocha.

    export default function Foo {
    const props = {
      text: '',
      isPublished: false
    }
    
    return (<div {...props} />);
    }
  • Ghi chú: Nên lọc các props không cần thiết khi có thể. Ngoài ra, sử dụng prop-types-exact để giúp ngăn ngừa lỗi.

    // tốt
    render() {
      const { irrelevantProp, ...relevantProps  } = this.props;
      return <WrappedComponent {...relevantProps} />
    }
    
    // tệ
    render() {
      const { irrelevantProp, ...relevantProps  } = this.props;
      return <WrappedComponent {...this.props} />
    }

Refs

  • Luôn sử dụng hàm gọi lại(callback) cho khai báo ref. eslint: react/no-string-refs

    // tệ
    <Foo
      ref="myRef"
    />
    
    // tốt
    <Foo
      ref={(ref) => { this.myRef = ref; }}
    />

Dấu ngoặc đơn

  • Đóng gói các thẻ JSX trong ngoặc đơn khi chúng kéo dài nhiều dòng. eslint: react/jsx-wrap-multilines

    // tệ
    render() {
      return <MyComponent variant="long body" foo="bar">
               <MyChild />
             </MyComponent>;
    }
    
    // Tốt
    render() {
      return (
        <MyComponent variant="long body" foo="bar">
          <MyChild />
        </MyComponent>
      );
    }
    
    // Tốt, Khi chỉ có 1 dòng
    render() {
      const body = <div>hello</div>;
      return <MyComponent>{body}</MyComponent>;
    }

Thẻ

  • Luôn luôn tự đóng các thẻ(tags) không có con. eslint: react/self-closing-comp

    // tệ
    <Foo variant="stuff"></Foo>
    
    // tốt
    <Foo variant="stuff" />
  • Nếu Component của bạn có thuộc tính nhiều dòng, hãy đóng thẻ đó trên 1 dòng mới. eslint: react/jsx-closing-bracket-location

    // tệ
    <Foo
      bar="bar"
      baz="baz" />
    
    // tốt
    <Foo
      bar="bar"
      baz="baz"
    />

Phương thức

  • Sử dụng arrow function để bao đóng các biến cục bộ.

    function ItemList(props) {
      return (
        <ul>
          {props.items.map((item, index) => (
            <Item
              key={item.key}
              onClick={() => làmGìĐó(item.name, index)}
            />
          ))}
        </ul>
      );
    }
  • Các hàm binding được gọi trong lúc render nên đặt ở trong hàm khởi tạo(constructor). eslint: react/jsx-no-bind

    Tại sao? Vì nếu bind trong hàm render thì mỗi khi render, hàm đó lại được tạo mới một lần khiến cho hiệu suất xử lí giảm.

    // tệ
    class MyComponent extends React.Component {
      onClickDiv() {
        // làm việc gì đó
      }
    
      render() {
        return <div onClick={this.onClickDiv.bind(this)} />;
      }
    }
    
    // tốt
    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
    
        this.onClickDiv = this.onClickDiv.bind(this);
      }
    
      onClickDiv() {
        // Làm gì đó vui vẻ
      }
    
      render() {
        return <div onClick={this.onClickDiv} />;
      }
    }
  • Không nên dùng dấu "_" đặt trước tên các hàm của Component

    Lí do? Vì dấu gạch dước thi thoảng được dùng trong một số ngôn ngữ để biểu thị tính "private". Tuy nhiên, không giống các ngôn ngữ khác, trong JavaScript, mọi thứ đều là “public”. Cho dù bạn có cho dấu gạch dưới vào hay không nó vẫn là public, bất kể ý định của bạn. Hãy xem vấn đề #1024, và #490 để hiểu sâu hơn.

    // tệ
    React.createClass({
      _onClickSubmit() {
        // làm việc gì đó
      },
    
      // làm việc gì đó
    });
    
    // tốt
    class extends React.Component {
      onClickSubmit() {
        // làm việc gì đó
      }
    
      // làm việc gì đó
    }
  • Phải trả về một giá trị trong hàm render. eslint: react/require-render-return

    // tệ
    render() {
      (<div />);
    }
    
    // tốt
    render() {
      return (<div />);
    }

Cách sắp xếp hàm

  • Các hàm trong class extends React.Component nên được viết theo thứ tự sau:
  1. Các phương thức tĩnh static (không bắt buộc)
  2. constructor
  3. getChildContext
  4. componentWillMount
  5. componentDidMount
  6. shouldComponentUpdate
  7. componentWillUpdate
  8. componentDidUpdate
  9. componentWillUnmount
  10. Hàm xử lí sự kiện như click hoặc submit onClickSubmit() & onChangeDescription()
  11. Các hàm lấy dữ liệu cho hàm render chẳng hạn như getSelectReason() hay getFooterContent()
  12. Các hàm render khác như renderNavigation() hay renderProfilePicture()
  13. render
  • Cách định nghĩa propTypesdefaultPropscontextTypes, ...

    import React from 'react';
    import PropTypes from 'prop-types';
    
    const propTypes = {
      id: PropTypes.number.isRequired, // Nếu id không đúng kiểu number, màn hình console sẽ hiện ra cảnh báo
      url: PropTypes.string.isRequired, // Nếu url không đúng kiểu string, màn hình console sẽ hiện ra cảnh báo
      text: PropTypes.string, // Nếu text không đúng kiểu string, màn hình console sẽ hiện ra cảnh báo
    };
    
    const defaultProps = {
      text: 'Hello World',  // Gán giá trị mặc định cho text
    };
    
    class Link extends React.Component {
      static methodsAreOk() {
        return true;
      }
    
      render() {
        return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a>;
      }
    }
    
    Link.propTypes = propTypes;
    Link.defaultProps = defaultProps;
    
    export default Link;
  • Các hàm trong React.createClass nên được viết theo thứ tự sau: eslint: [react/sort-comp`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md)

  1. displayName
  2. propTypes
  3. contextTypes
  4. childContextTypes
  5. mixins
  6. statics
  7. defaultProps
  8. getDefaultProps
  9. getInitialState
  10. getChildContext
  11. componentWillMount
  12. componentDidMount
  13. componentWillReceiveProps
  14. shouldComponentUpdate
  15. componentWillUpdate
  16. componentDidUpdate
  17. componentWillUnmount
  18. Hàm xử lí sự kiện như onClickSubmit() hay onChangeDescription()
  19. Các hàm lấy dữ liệu cho phương thức render nhưgetSelectReason() hay getFooterContent()
  20. Các hàm render khác như renderNavigation() hay renderProfilePicture()
  21. render

Thuộc tính isMounted

Tại sao? Vì isMounted là một anti-pattern(mẫu nên tránh), không có sẵn khi dùng ES6 classes, và đang bị phản đối từ cộng đồng.

The OCR Service to extract the Text Data

Optical character recognition, or OCR, is a key tool for people who want to build or collect text data. OCR uses machine learning to extract...