[ReactJS] Handling Events & Conditional Rendering

React JS - thuật ngữ không còn xa lạ đối với cá nhân mình. Tuy nhiên, mặc dù nghe đến nó nhiều nhưng để mà ngồi đào sâu nghiên cứu về nó thì quả thật là chưa có lúc nào ngồi tìm hiểu và nghiên cứu về nó kỹ lưỡng, cẩn thận và tỉ mỉ cả. Nhân lúc rảnh rỗi, thử tìm kiếm tài lại và học hỏi về React JS xem sao. Việc đầu tiên mình nghĩ đến khi có một keyword đó là lên google search tài liệu. "ReactJS là gì?". Kết quả trả về cũng kha khá.

React là một thư viện viết bằng javascript, dùng để xây dựng giao diện người dùng(User Interface – UI)

Sáu khi tìm hiểu những thứ căn bản như là cài đặt, chạy chương trình hello world rồi components, props, ... Đến phần này, Handing Events, thiết nghĩ lên ghi lại để sau này còn có tài liệu tham khảo. ^^

Handling Events

Câu đầu tiên mà document của ReactJS nói đến về phần này là: "Handling events với React Element cũng tương tự như handling event trên DOM Element" nó chỉ khác nhau ở một số điểm sau:

  • Tên của React Events được đặt theo kiểu camelCase chứ không phải lowercase
  • Truyền JSX vào một function để handle event chứ không phải là một string

Ví dụ, với HTML:

<button onclick="activateLasers()">
  Activate Lasers
</button>

Nhưng trong React,

<button onClick={activateLasers}>
  Activate Lasers
</button>

Một điểm khác biệt nữa giữa React và Dom là bạn không thể gọi return false để dừng hành động mặc định (prevent default) trong React. Bạn phải gọi preventDefault. Ví dụ, trong HTML để ngăn chặn việc mở 1 trang mới khi bạn click vào link.

<a href="#" onclick="console.log('The link was clicked.'); return false">
  Click me
</a>

Nhưng trong React

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

Ở đây, e là tổng hợp tất cả event. React js xác định các event này theo W3C spec. Khi sử dụng React, bạn không cần gọi function addEventListener để lắng nghe sự kiện vào DOM khi nó tượng tạo mới. Thay vào đó, chỉ cần khai báo một sự kiện lắng nghe khi nó được hiển thị lần đầu. Ví dụ, với component Togged, sẽ cho phép người dùng click vào button chuyển trạng thái từ ON -> OFF.

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

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

Lưu ý: Cẩn phải thận trọng với việc sử dụng this trong việc JSX callbacks. Trong Javascript, các method của class không bị ràng buộc bởi mặc định. Nếu bạn quên không gọi this.handleClick mà gọi thằng onClick khi đó this sẽ bị lỗi undefined khi mà function được gọi.

Nếu bạn thấy gọi binds là bất tiện. Có 2 cách giúp bạn cải thiện việc này. Sử dụng field class để gọi

class LoggingButton extends React.Component {
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

Sử dungj arow function:

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

Passing Arguments to Event Handlers

Để truyền tham số vào event handlers, có thể dùng theo 1 trong số cách sau:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

Trong cả hai trường hợp, tham số e đại diện cho React Event sẽ được truyền như là tham số thứ 2 sau id.

Conditional Rendering

Trong React bạn có thể tạo các component riêng biệt chứa những hành động bạn cần. Conditional Rendering hoạt động tương tự với Conditional trong Javascript. Sử dụng javascript operator như là if tạo các phần tử đại diện cho trạng thái hiện tại.

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

Chúng ta sẽ tạo một component Greeting hiển thị một trong 2 thành phần bên trên tùy thuộc vào việc người dùng có login vào hệ thống hay không:

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  // Try changing to isLoggedIn={true}:
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);

Ví dụ này tạo Greeting component phụ thuộc vào giá trị của biến isLoggedIn

Element Variables

Có thể dùng các biến để lưu trữ giá trị. Điều này giúp bạn Condition render một phần của component trong khi những phần còn lại không hề thay đổi.

function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Login
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Logout
    </button>
  );
}

Trong ví dụ này, chúng ta sẽ tạo một stateful component gọi là LoginController. Nó sẽ render <LoginButton /> hoặc <LogoutButton />.

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;

    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

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

Khai báo một biến và sử dụng if là cách tốt nhất để render một thành phần có điều kiện