Components and props

Components giúp bạn chia giao diện thành các phần độc lập, có thể tái sử dụng, và nghĩ về từng mảnh trong cô lập. Trang này cung cấp phần giới thiệu về ý tưởng của components. Về mặt khái niệm, components giống như các hàm của Javascript. Chúng nhận đầu vào bất kỳ (được gọi là “props”) và trả về React elements mô tả những gì nên hiển thị trên màn hình.

Function and class components

Cách đơn giản nhất để định nghĩa component là viết 1 hàm của javascript:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Hàm này là một React component bởi nó chấp nhận một “props” đơn (viết tắt của properties) biến object với dữ liệu và trả về một React element. Chúng ta gọi components đó là “function components” bởi chúng chính là hàm của javascript.

Bạn cũng có thể dùng ES6 để định nghĩa component:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Hai components ở trên là tương đương trên góc nhìn của React.

Hàm và lớp components đều có vài chức năng bổ sung mà chúng tôi sẽ giải thích trong phần tiếp theo.

Rendering a Component

Trước đây, chúng ta chỉ được (gặp) thấy React elements đại diện cho tags của DOM:

const element = <div />;

Tuy nhiên, elements cũng có thể đại diện cho component mà người dùng tự định nghĩa:

const element = <Welcome name="Sara" />;

Khi React thấy một element đại diện cho component người dùng tự định nghĩa, nó sẽ truyền các thuộc tính JSX và con vào component đó như một object. Chúng ta gọi object đó là “props”.

Với ví dụ, phần code này render “Hello,Sara” trên trang:

function Welcome(props) { 
 return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;ReactDOM.render(
  element,
  document.getElementById('root')
);

Hãy xét lại những gì trong ví dụ này:

  1. Chúng ta gọi ReactDOM.render() với element <Welcome name=”Sara”/>
  2. React gọi component Welcome với props { name: ’Sara’ }
  3. Component Welcome trả về element <h1>Hello, Sara</h1> như một kết quả.
  4. ReactDOM cập nhật DOM để khớp với thẻ <h1>Hello, Sara</h1> một cách hiệu quả

Note: Luôn luôn bắt đầu tên component với chữ viết hoa.

React xem component bắt đầu với chữ thường như tags của DOM. Ví dụ,

đại diện cho thẻ div của HTML, nhưng đại diện cho một component và yêu cầu trong phạm vi của Welcome.

Để học thêm về lý do đằng sau quy tắc này, hãy đọc JSX in depth.

Biên soạn Components

Components có thể sử dụng các components khác trong output. Điều này cho phép chúng ta sử dụng cùng trừu tượng hóa component cho bất kỳ mức độ chi tiết nào. Nút,form, hộp thoại, màn hình: trong React apps tất cả đều được thể hiện thông thường như một components.

Ví dụ, chúng ta tạo ra component App render thẻ Welcome nhiều lần:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />      
      <Welcome name="Cahal" />      
      <Welcome name="Edite" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

Thông thường, React apps mới có một component App ở phần đầu. Tuy nhiên, nếu bạn tích hợp React vào một app có sẵn, bạn nên bắt đầu từ dưới lên với một component nhỏ như Button và dần dần làm theo cách của bạn đến phần cao nhất trong hệ thống view.

Trích xuất components

Đừng sợ việc tách các component thành các component nhỏ hơn.
Ví dụ, thử xem xét component Comment này nhé:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

Component này chấp nhận author (một object), text ( một chuỗi), và date (biến date) như biến, và miêu tả một bình luận trên website mạng xã hội.

Component này có thể khó khăn để thay đổi bởi vì tất cả kết nối, và nó cũng khó để tái sử dụng các phần riêng tư của nó. Hãy tách một vài component từ nó ra nhé.

Đầu tiên, chúng ta tách phần Avatar:

function Avatar(props) {
  return (
    <img className="Avatar"      
          src={props.user.avatarUrl}      
          alt={props.user.name}  
      />
  );
}

Component Avatar không cần biết rằng nó được render ở bên trong component Comment. Đây chính là tại sao chúng ta phải truyền biến có tên khái quát hơn: user thay vì author.

Chúng tôi khuyên bạn đặt tên biến từ góc nhìn của component đó thay vì bối cảnh mà nó đang được sử dụng.

Và chúng ta có thể làm Comment đơn giản hơn một chút:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <Avatar user={props.author} />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

Tiếp theo, chúng ta sẽ tách component UserInfo render Avatar bên cạnh tên người dùng:

function UserInfo(props) {
  return (
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </div>  );
}

Hàm này còn giúp Comment đơn giản hơn nữa:

function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author} />
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

Tách component ban đầu có thể là công việc lộn xộn, nhưng có được một bảng những component có thể tái sử dụng rất đáng giá trong những app lớn. Một quy tắc nhỏ là một phần trong giao diện của bạn được sử dụng nhiều lần (Button, Panel, Avatar ), hoặc đủ khó ( App, FeedStory, Comment ), nó là ứng cử viên tốt để trở thành component có thể tái sử dụng.

Props chỉ có thể đọc

Dù bạn có khai báo một component như một function hay một class, component phải không bao giờ thay đổi thuộc tính của chính nó. Xem thử function sum sau:

function sum(a, b) {
  return a + b;
}

Những function được gọi là “pure” bởi vì chúng không cố thay đổi đầu vào, luôn luôn trả về cùng một giá trị với cùng một giá trị đầu vào.

Ngược lại, function là “impure” bởi vì nó thay giá trị đầu vào:

function withdraw(account, amount) {
  account.total -= amount;
}

React rất linh hoạt nhưng cũng có một quy tắc nghiêm ngặt:

Tất cả React components phải thể hiện như hàm “nguyên chất” với sự tôn trọng cho biến của chúng

Tất nhiên, giao diện ứng dụng là thay đổi và thay đổi theo thời gian. Trong phần tiếp theo, chúng tôi sẽ giới thiệu khái niệm mới của “state”. State cho phép React components thay đổi đầu ra của nó theo thời gian đáp lại hành động của người dùng, phản hồi kết nối, một vài thứ khác, mà không cần vi phạm luật trên.