The React Cheatsheet for 2021(+ Real-World Examples) - Part I

The React Cheatsheet for 2021(+ Real-World Examples) - Part I

Visual Cheatsheet sẽ giúp bạn master tất cả các khái niệm và tính năng chính của thư viện React trong 2021, nó cũng sẽ giúp bạn tối ưu hoá việc học React trong một khoảng thời gian ngắn nhất .

Nó bao gồm rất nhiều ví dụ thực tế để minh hoạ mọi tính năng của library và cách nó hoạt động bằng cách sử dụng các patterns mà bạn có thể áp dụng trong các dự án của riêng mình.

Cùng với mỗi đoạn code, tác giả đã thêm rất nhiều helpful comments. Nếu bạn đọc những comments đó, bạn sẽ hiểu mỗi dòng mã có chức năng gì, các khái niệm khác nhau có liên quan đến nhau như thế nào và từ đó có thể hiểu được đấy đủ hơn về cách React được sử dụng.

Download the cheatsheet in the PDF format here (it takes 5 seconds)

Table of Contents

React Fundamentals

  • JSX Elements

  • Components and Props

  • Lists and Keys

  • Even Listeners and Handling Events

Essential React Hooks

  • State and useState

  • Side Effects and useEffect

  • Refs and useRef

Hooks and Performance

  • Preventing Re-renders and React.memo

  • Callback functions and useCallback

  • Memoization and useMemo

Advanced React Hooks

  • Context and useContext

  • Reducers and useReducer

  • Writing custom hooks

  • Rules of hooks

React Fundamentals

JSX Elements

Ứng dụng React được cấu trúc bằng syntax được gọi là JSX. Dưới đây là syntax của một JSX element cơ bản :

/* 
  JSX cho phép chúng ta viết theo cú pháp gần giống với pain HTML.
  As a result, JSX is công cụ mạnh mẽ để cấu trúc các ứng dụng.
  JSX sử dụng tất cả các valid HTML (i.e. div/span, h1-h6, form/input, img, etc).
*/

<div>Hello React!</div>

/* 
  Note: JSX này sẽ không được hiển thị bởi vì nó cần được rendered bởi ứng dụng của chúng ta sử dụng ReactDOM.render()
*/

JSX là cách phổ biến nhất để cấu trúc ứng dụng React, nhưng nó không phải là bắt buộc.

/* JSX là cách đơn giản nhất để sử dụng function React.createElement()
 Nói cách khác, trong React 2 dòng dưới là giống nhau: */

<div>Hello React!</div>  // JSX syntax

React.createElement('div', null, 'Hello React!'); // createElement syntax

JSX không được hiểu bởi trình duyệt . Nó cần được biên dịch sang pain Javascript, thứ là browser có thể hiểu được.

Trình biên dịch được sử dụng phổ biến nhất JSX được gọi là Babel.

/* 
  Khi ứng dụng được xây dựng chạy ở trình duyệt, JSX sẽ được Babel chuyển đổi thành lệnh gọi hàm React.createElement(). 
  từ... 
*/
const greeting = <div>Hello React!</div>;

/* ...thành: */
"use strict";

const greeting = /*#__PURE__*/React.createElement("div", null, "Hello React!");

JSX khác với HTML ở một số điểm quan trọng:

/* 
  Chúng ta có thể viết JSX giống như HTML thuần tuý, nhưng nó thực sự được tạo bởi các hàm Javascript.
  Vì JSX là Javascript, không phải HTML nên có một số điểm khác biệt:

  1)Một số thuộc tính JSX lại được đặt tên khác với HTML. Why? Bởi vì một số từ thuộc tính là các từ dành riêng trong Javascript. Chẳng hạn như 'class' . Thay vì dùng 'class', JSX sử dụng 'className'

   Ngoài ra, bởi vì JSX là Javascript, các thuộc tính gồm nhiều từ được viết bằng camelcase :
*/
<div id="header">
  <h1 className="title">Hello React!</h1>
</div>

/* 
  2)  Các phần tử JSX chỉ bao gồm một thẻ duy nhất (tức là các phần tử input, img, br, ...) phải được đóng bằng dấu (/) phía sau: 
*/

<input type="email" /> // <input type="email"> is a syntax error

/* 
  3) Các phần tử JSX bao gồm thẻ mở và thẻ đóng (i.e div , span, button) phải có cả hai hoặc được đóng bằng dấu gạch chéo ở phía trước.
*/

<button>Click me</button> // <button> or </button> is a syntax error
<button /> // empty, but also valid

Inline styles có thể được thêm vào các phần tử JSX bằng cách sử dụng thuộc tính style, Và các styles phải được updated trong một object, không phải như với HTML.

Lưu ý rằng tên thuộc tính cũng phải được viết bằng camelcase.

/* 
  Các thuộc tính chấp nhận giá trị pixel (like width, height, padding, margin, etc), có thể sử dụng kiểu số integers thay vì string.
*/
<h1 style={{ color: 'blue', fontSize: 22, padding: '0.5em 1em' }}>
  Hello React!
</h1>

JSX cung cấp toàn bộ sức mạnh của Javascript ngay trong giao diện người dùng.

const greeting = <div>Hello React!</div>;

const isNewToReact = true;

function sayGreeting() {
  if (isNewToReact) {
    return greeting; // displays: Hello React!
  } else {
    return <div>Hi again, React</div>;
  }
}

JSX cho phép chèn (hoặc nhúng) các biểu thức Javascript đơn giản bằng cú pháp bên trong dấu ngoặc nhọn {}.

const year = 2021;

const greeting = <div>Hello React in {year}</div>;

const goodbye = <div>Goodbye previous year: {year - 1}</div>

const className = 'title';
const title = <h1 className={className}>My title</h1>

JSX cũng cho phép chúng ta lồng các phần tử vào nhau giống như HTML.

const greeting = (
  // div is the parent element
  <div>
    <h1>Hello!</h1>
    <p>Welcome to React</p>
  </div>
);

JSX cũng cho phép chúng ta viết comment nhiều dòng, like this :

const greeting = (
  <div>
    {/* This is a single line comment */}
      <h1>Hello!</div>
    <p>Welcome to React</p>
    {/* This is a 
      multiline
      comment */} 
  </div>
);

Tất cả các ứng dụng React đều yêu cầu 3 thứ :

  1. ReactDOM.render() : được sử dụng đê render ứng dụng của chúng ta bằng cách mounting vào một phần tử HTML.

  2. Một JSX element : được gọi là "root node", bởi vì nó là gốc của ứng dụng chúng ta và tất cả các children sẽ được rendering bên trong nó.

  3. Phần tử HTML (DOM) element: Nơi ứng dụng được chèn vào trang HTML . Phần tử thường có id là "root", nằm trong tệp index.html.

import React from "react";
import ReactDOM from "react-dom";

// root node (usually a component) is most often called "App"
const App = <h1>Hello React!</h1>;

// ReactDOM.render(root node, HTML element)
ReactDOM.render(App, document.getElementById("root"));

Components and Props

JSX có thể được nhóm lại cùng nhau với các chức năng riêng biệt được gọi là components.

Có 2 loại components trong 1 ứng dụng React đó là : functions componentclass components.

Tên components được viết hoa để phân biệt với các hàm javascript không trả về JSX.

import React from "react";

/*     
  Function component
  Lưu ý tên hàm được viết hoa: 'Header', not 'header'
*/
function Header() {
  return <h1>Hello React</h1>;
}

// Function components cũng hợp lệ khi sử dụng arrow function 
const Header = () => <h1>Hello React</h1>;

/* 
  Class component
  Lưu ý từ khoá 'extends' và 'render' method)
*/
class Header extends React.Component {
  render() {
    return <h1>Hello React</h1>;
  }
}

Components mặc dù là functions nhưng chúng không được gọi như các hàm javascript thông thường. Chúng được thực thi bằng cách rendering giống như với JSX trong ứng dụng của bạn.

//Chúng ta có gọi function component giống như một hàm bình thường không?

// No, thực thi chúng và hiển thị JSX
const Header = () => <h1>Hello React</h1>;

// ... Chúng ta sử dụng chúng làm 'custom' JSX elements
ReactDOM.render(<Header />, document.getElementById("root"));
// renders: <h1>Hello React</h1>

Lợi ích lớn nhất của các thành phần là khả năng chúng ta có thể sử dụng lại chúng ở bất kì đâu trong ứng dụng của chúng ta.

Vì các components tận dụng sức mạnh của các hàm javascript, nên chúng ta dễ dàng chuyển dữ liệu cho chúng một cách hợp lý.

/* 
  The Header and Footer components có thể được sử dụng ở bất kì nơi nào trong ứng dụng của chúng ta.
*/

// IndexPage component, visible on '/' route of our app
function IndexPage() {
  return (
    <div>
      <Header />
      <Hero />
      <Footer />
    </div>
  );
}

// AboutPage component, visible on the '/about' route
function AboutPage() {
  return (
    <div>
      <Header />
      <About />
      <Testimonials />
      <Footer />
    </div>
  );
}

Dữ liệu được vận chuyển giữa các components trong Javascript được gọi là props. Props trông giống với attributes on plain JSX/HTML elements. Nhưng bạn có thể truy nhập các giá trị của chúng trong chính components đó.

Props có sẵn trong tham số của các components mà chúng được truyền vào.

/* 
  Làm thế nào để pass custom data cho component của mình từ parent component?
  Ví dụ, để hiển thị user's name trong app header.
*/

const username = "John";

/* 
  Để làm thế, Chúng ta thêm custom 'attributes' vào our component được gọi là props.
  Chúng ta có thể thêm nhiều nhưng cần phải đặt tên chúng sao cho phù hợp với dữ liệu truyền vào.
  Để chuyển user's name vào header, Chúng tôi sử dụng a prop called 'username'
*/
ReactDOM.render(
  <Header username={username} />,
  document.getElementById("root")
);
// Chúng ta gọi props này là 'username' nhưng có thể đặt tên bất kì như là một biến javascript.

// props là object mà bất kì thành phần nào nhận được như là một đối số
function Header(props) {
  return <h1>Hello {props.username}</h1>;
}

Props không bao giờ được thay đổi trực tiếp trong child component.

Nói cách khác rằng props không bao giờ được thay đổi.

/* 
  Components phải hoạt động như 'pure' functions.
  Có nghĩa là, với mọi input, chúng ta mong đợi cùng một output.
  Tương đương với chúng ta không thể thay đổi props object, only read from it.
*/

// Chúng ta không thể thay đổi props object :
function Header(props) {
  props.username = "Doug";

  return <h1>Hello {props.username}</h1>;
}
/* 
  Nhưng nếu chúng ta muốn thay đổi giá trị của props được truyền thì sao?
  Đó là nơi chúng ta sử dụng state (see the useState section).
*/

The children props là cực kì hữu ích nếu bạn muốn pass elements / components làm props cho các thành phần khác.

// Chúng ta có thể chấp nhận React elements (or components) as props?
// Yes,thông qua một thuộc tính đặc biệt trên props object được gọi là  'children'

function Layout(props) {
  return <div className="container">{props.children}</div>;
}

// The children prop is very useful for when you want the same
function IndexPage() {
  return (
    <Layout>
      <Header />
      <Hero />
      <Footer />
    </Layout>
  );
}

// different page, but uses same Layout component (thanks to children prop)
function AboutPage() {
  return (
    <Layout>
      <About />
      <Footer />
    </Layout>
  );
}

Vì các components là các biểu thức Javascript vì thế chúng ta có thể sử dụng chng kết hợp với các câu lệnh if else, like this :

function Header() {
  const isAuthenticated = checkAuth();

  /* Nếu user đã được xác thực, hiển thị authenticated app, nếu không, the unauthenticated app */
  if (isAuthenticated) {
    return <AuthenticatedApp />   
  } else {
    return <UnAuthenticatedApp />   
  }
}

Để sử dụng câu điều kiện trong component trả về JSX , chúng ta có thể sử dụng (&& and || operators)

function Header() {
  const isAuthenticated = checkAuth();

  return (
    <nav>
      {/* if isAuth is true, show nothing. If false, show Logo  */}
      {isAuthenticated || <Logo />}
      {/* if isAuth is true, show AuthenticatedApp. If false, show Login  */}
      {isAuthenticated ? <AuthenticatedApp /> : <LoginScreen />}
      {/* if isAuth is true, show Footer. If false, show nothing */}
      {isAuthenticated && <Footer />}
    </nav>
  );
}

Fragments là một components đặc biệt để hiển thị nhiều thành phần mà không cần thêm elements vào DOM. Chúng là lý tưởng cho logic điều kiện có nhiều thành phần.

/*
  Chúng ta cải thiện logic trong ví dụ trước.
  If isAuthenticated is true, làm sao hiển thị cả the AuthenticatedApp and Footer components?
*/
function Header() {
  const isAuthenticated = checkAuth();

  return (
    <nav>
      <Logo />
      {/* 
        Chúng ta kết xuất cả hai components with a fragment. 
        Fragments rất ngắn gọn: <> </>
      */}
      {isAuthenticated ? (
        <>
          <AuthenticatedApp />
          <Footer />
        </>
      ) : (
        <Login />
      )}
    </nav>
  );
}
/* 
  Note: An alternate syntax for fragments is React.Fragment:
  <React.Fragment>
     <AuthenticatedApp />
     <Footer />
  </React.Fragment>
*/

Lists and Keys

Sử dụng .map() function để chuyển danh sách dữ liệu (arrays) thành danh sách elements.

const people = ["John", "Bob", "Fred"];
const peopleList = people.map(person => <p>{person}</p>);

.map() có thể được sử dụng tốt cho components cũng như pain JSX elements.

function App() {
  const people = ['John', 'Bob', 'Fred'];
  // can interpolate returned list of elements in {}
  return (
    <ul>
      {/* Chúng ta chuyển từng phần tử mảng làm prop cho Person component */}
      {people.map(person => <Person name={person} />}
    </ul>
  );
}

function Person({ name }) {
  //  Chúng ta có thể truy cập trực tiếp 'name' prop sử dụng object destructuring
  return <p>This person's name is: {name}</p>;
}

Mỗi React element trong danh sách các phần tử nên có một special key prop. Keys là điều cần thiết để React có thể theo dõi từng phần tử đang được lặp lại với .map() function.

React sử dụng key để cập nhật các phần tử riêng lẻ một cách hiệu quả khi chúng thay đổi (thay vì hiển thị lại toàn bộ danh sách).

Keys cần các giá trị duy nhất để có thể xác định theo từng giá trị khoá của chúng.

function App() {
  const people = [
    { id: 'Ksy7py', name: 'John' },
    { id: '6eAdl9', name: 'Bob' },
    { id: '6eAdl9', name: 'Fred' },
  ];

  return (
    <ul>
      {/* keys cần phải là các giá trị nguyên thuỷ, lý tưởng là một chuỗi duy nhất, such as an id */}
      {people.map(person =>
         <Person key={person.id} name={person.name} />
      )}
    </ul>
  );
}

// Nếu bạn không có id với giá trị nguyên thuỷ duy nhất thì bạn có thể sử dụng tham số thưs 2 của .map() để lấy từng chỉ mục.

function App() {
  const people = ['John', 'Bob', 'Fred'];

  return (
    <ul>
      {/* use array element index for key */}
      {people.map((person, i) => <Person key={i} name={person} />)}
    </ul>
  );
}

Event Listeners and Handling Events

Việc lắng nghe các sự kiện trên các phần tử JSX so với các phần tử HTML khác nhau theo một số cách quan trọng.

Đầu tiên, bạn không thể lắng nghe các sự kiện trên các thành phần React - chỉ trên các phần tử JSX.

/* 
  Quy định cho hầu hết các hàm xư lý sự kiện chính là đặt tiền tố chúng bằng 'handle' sau đó là hành động mà chúng thực hiện.
*/
function handleToggleTheme() {
  // code to toggle app theme
}

/* In HTML, onclick đều là chữ thường, cộng với trình xử lý sự kiện bao gồm một tập hợp các dấu ngoặc đơn sai khi được tham chiêus */
<button onclick="handleToggleTheme()">
  Toggle Theme
</button>

/* 
  In JSX, onClick is camelcase, giống như attributes / props.
  Chúng tôi cũng chuyển một tham chiếu đến hàm với dấu ngoặc nhọn.
*/
<button onClick={handleToggleTheme}>
  Toggle Theme
</button>

Các sự kiện React cần biết nhất là onClick, onChange and onSubmit.

  • onClick xử lý các sự kiện nhấp chuột trên JSX elements (cụ thể là buttons).

  • onChange xử lý các sự kiện bàn phím (cụ thể là người dùng nhập vào một đầu vào hoặc vùng văn bản).

  • onSubmit xử lý việc gửi biểu mẫu từ người dùng.

function App() {
  function handleInputChange(event) {
    /* Khi truyền hàm cho trình xử lý sự kiện, như onChange , chúng ta có quyền truy cập vào dữ liệu về sự kiện. */
    const inputText = event.target.value; // text typed into the input
    const inputName = event.target.name; // 'email' from name attribute
  }

  function handleClick(event) {
    /* onClick thường không cần dữ liệu sự kiện, nhưng nó cũng nhận dữ liệu sự kiện mà chúng ta có thể sử dụng */
    console.log('clicked!');
    const eventType = event.type; // "click"
    const eventTarget = event.target; // <button>Submit</button>
  }

  function handleSubmit(event) {
    /* 
     When we hit the return button, biểu mẫu sẽ được gửi, cũng như là khi button type="submit" is clicked.
     Khi chúng tôi gọi event.preventDefault() để ngăn chặn hành vi mặc định diễn ra, đó là gửi một yêu cầu http và tải lại trang.
    */
    event.preventDefault();
    const formElements = event.target.elements; // access all element within form
    const inputValue = event.target.elements.emailAddress.value; // access the value of the input element with the id "emailAddress"
  }

  return (
    <form onSubmit={handleSubmit}>
      <input id="emailAddress" type="email" name="email" onChange={handleInputChange} />
      <button onClick={handleClick}>Submit</button>
    </form>
  );
}

(...Còn phần sau nhé ❤️❤️)

Happy coding! ❤️

Reference

  1. freecodecamp.org/news/react-cheatsheet-with..