12/08/2018, 14:57

Một vàikhái niệm cơ bản trong React

React.JS là một thư viện Javascript dùng để xây dựng giao diện người dùng. Được tạo ra bởi Facebook , React càng ngày càng được sử dụng rộng rãi, đặc biệt là trong các trang web đòi hỏi yêu cầu cao về giao diện với các khả năng nổi bật như nhanh, dễ học, code ngắn và tái sử dụng tốt. Trong bài ...

React.JS là một thư viện Javascript dùng để xây dựng giao diện người dùng. Được tạo ra bởi Facebook, React càng ngày càng được sử dụng rộng rãi, đặc biệt là trong các trang web đòi hỏi yêu cầu cao về giao diện với các khả năng nổi bật như nhanh, dễ học, code ngắn và tái sử dụng tốt. Trong bài viết này, tôi sẽ mô tả vài khái niệm cơ bản để bắt đầu với React.

Component

ReactJs xây dựng ứng dụng xung quanh các component, chứ không dùng template như các framework khác. Component được tạo ra bằng các gọi phương thức createClass của đối tượng React.

# Vd: tạo button submit
var Button = React.createClass({
    render: function(){
        return (
            <input type="submit" />
        );
    }
});

Hàm createClass nhận vào một tham số, là đối tượng mô tả đặc tính của component. Đối tượng này bao gồm tất cả các phương thức để hình thành nên component. Phương thức quan trọng nhất là render, phương thức này được trigger khi component đã sẵn sàng để được render lên trên page.

Trong hàm đó, bạn sẽ trả về một mô tả cho việc bạn muốn React render cái gì lên trên page. Như trong ví dụ ở trên, đơn giản tôi muốn render một button.

Hàm render chính là mô tả cụ thể của UI tại bất cứ thời điểm nào. Vì thế nếu dữ liệu thay đổi, React sẽ thực hiện việc update UI với dữ liệu tương ứng. Khi dữ liệu thay đổi, React sẽ tự động gọi hàm render để update lại UI.

Multiple components

Nếu muốn lồng nhiều component vào nhau, bạn sẽ làm điều này trong lệnh return của phương thức render.

var Form = React.createClass({
    render: function(){
        return (
            <div>
                <h3>Click the button</h3>
                <input type="submit" />
            </div>
        );
    }
});
var App = React.createClass({
    render: function(){
        return (
            <div>
                <h1> Welcome to my app!</h1>
                <Form />
            </div>
        );
    }
});
React.render(<App />,  document.getElementById("app"));

Ở ví dụ trên, Form component được lồng vào trong App component. Đây là một dạng quan hệ cha con.

Phương thức React.render() ở trên nhằm mục đích kích hoạt việc render, và render thừ root component, trong trường hợp trên là App vào trong DOM với container cụ thể là element có id là app.

Props & State là gì?

Có hai kiểu của data trong React đó là props và state

Điểm mấu chốt của sự khác nhau giữa 2 kiểu data là state thì private và chỉ có thể được thay đổi bên trong bản thân component. Props thì mang tính external, và không bị kiểm soát bởi bản thân component. Nó được truyền từ component cao hơn theo phân cấp, hay có thể hiểu đơn giản là truyền từ component cha xuống component con, cái mà điều khiển dữ liệu trước khi truyền xuống.

Vì thế trong khi một component không thể thay đổi props của nó một cách trực tiếp (điều này có thể làm một cách gián tiếp), thì nó có thể tự thay đổi state của bản thân.

Props

Ví dụ, ta có một biến text đơn giản sau:

var text = "Click button";

để đưa props vào một component cũng tương tự như khai báo 1 attribute cho thẻ HTML

<App text={text} />

Một khi App component được cài đặt như thế này, nó có thể truy xuất vào biến text mà ta đã khai báo ở trên thông qua lời gọi this.props.text. Tuy nhiên, nó không thể trực tiếp thay đổi dữ liệu. Nó chỉ là thông tin được cài đặt cho component.

var text = "Click the button";

var Form = React.createClass({
    render: function(){
        return (
            <div>
                <h3>{this.props.text}</h3>
                <input type="submit" />
            </div>
        );
    }
});
var App = React.createClass({
    render: function(){
        return (
            <div>
                <h1> Welcome to my app!</h1>
                <Form text={this.props.text}/>
            </div>
        );
    }
});
React.render(<App text={text}/>,  document.getElementById("app"));

Props được truyền vào trong App component trong phương thức React.render(). Sau đó App component có thể truy xuất biến text thông qua lời gọi this.props.text. Nó cũng có thể truyền dữ liệu xuống component con của nó như chúng ta thấy cách mà Form component được App component cài đặt props trong ví dụ.

Khi dữ liệu đến được Form component, chúng ta thấy đây là điểm kết thúc, dữ liệu sẽ được render ra thẻ h3 như trên.

Đây là cách mà dữ liệu được luân chuyển trong React thông qua props.

State

Một cách khác để lưu trữ dữ liệu trong React là state. Không giống như props, bất biến dưới góc nhìn của component thì state có thể thay đổi.

Vì thế nếu bạn muốn dữ liệu trong ứng dụng thay đổi, ví dụ như dựa trên tương tác người dùng, thì dữ liệu phải được lưu trữ trong component state.

State là private và được quản lý bởi chỉ duy nhất một component, nó không thể truyền xuống cho component con. Nếu bạn muốn truyền xuống cho component con thì bạn phải truyền nó như là một props.

Cài đặt state: Để cài đặt state, đơn giản chúng ta cài đặt hàm getInitialState() vào component, và trả về bất cứ gì bạn muốn cài đặt trong state của component đó.

Thay đổi state Để thay đổi state, đơn giản ta gọi hàm this.setState(), và truyền vào state mới như là một tham số.

var App = React.createClass({
    getInitialState: function(){
        return {
            active: true
        }
    },
    handleClick: function(){
        this.setState({
            active: !this.state.active
        });
    },
    render: function(){
        var buttonSwitch = this.state.active ? "On" : "Off";
        return (
            <div>
                <p>Click the button!</p>
                <input type="submit" onClick={this.handleClick} />
                <p>{buttonSwitch}</p>
            </div>
        );
    }
});

React.render(<App />,  document.getElementById("app"));

Đoạn code trên ta cài đặt event onClick vào button. Khi nó được trigger, chúng ta gọi hàm handleClick, cái mà đã được cài đặt trước đó, và luôn sẵn sàng được gọi thông qua từ khóa this. Trong hàm handleClick, chúng ta gọi this.setState(), cái mà sẽ thay đổi trạng thái của component.

Tuy nhiên, bạn nên cố gắng giữ số lượng các stateful component ít nhất có thể, và thậm chí giữ tối thiểu lượng dữ liệu trong state. Nếu component cấp dưới cần truy xuất dữ liệu từ state, thì hãy truyền nó thông qua props.

Để đặt các state ở đâu, chúng ta nên xác định dựa theo các tiêu chí:

  • Xác định mỗi component mà render thông tin gì đó dựa trên state.
  • Tìm một component mà nó chủ sở hữu chung của các component khác (một component nằm bên trên tất cả các component khác trong hệ thống phân cấp thì cần có state)
  • Nếu bạn không thể tìm ra component nào phù hợp, hãy tạo một component mới đơn giản giữ nhiệm vụ lưu trữ state và đặt nó đâu đó nằm bên trên các component là chủ sở hữu chung trong hệ thống phân cấp.

Inverse data flow

Ở trên ta đã đề cập đến luồng dữ liệu chỉ có một chiều trong React, ngoài ra vẫn có cách để thêm một dòng dữ liệu theo hướng ngược lại.

Bạn sẽ cần điều này khi mà một component nằm sâu bên trong cây phân cấp cần phải thay đổi trạng thái của cha nó.

Ví dụ về việc làm thế nào để khi click vào button trong Form component mà nó sẽ trigger việc thay đổi trạng thái (state change) trong App component, cái nằm bên trên nó, và cách để truy xuất vào phương thức onUserClick.

var Form = React.createClass({
    render: function(){
        return (
            <div>
                <input type="submit" onClick={this.props.onUserClick} />
                <h3>You have pressed the button {this.props.counter} times!</h3>
            </div>
        );
    }
});

var App = React.createClass({
    getInitialState: function(){
        return {
            counter: 0
        }
    },
    onUserClick: function(){
        var newCount = this.state.counter += 1;
        this.setState({
            counter: newCount
        });
    },
    render: function(){
        return (
            <div>
                <h1> Welcome to the counter app!</h1>
                <Form counter={this.state.counter} onUserClick={this.onUserClick} />
            </div>
        );
    }
});

React.render(<App />,  document.getElementById("app"));

Như bạn có thể thấy, chúng ta chỉ đơn giản truyền xuống phương thức onUserClick như là một props, đã có thể kích hoạt việc tương tác ngược từ Form component lên App component, và trigger một trong số những method của nó.

Thuộc tính key

Khi bạn tạo các component một cách dynamically, mỗi thành phần đều cần thuộc tính key, và thuộc tính này là duy nhất (unique). Trong suốt quá trình rendering, các component sẽ bị xáo trộn, chúng cũng có thể bị destroy hay recreate tùy vào sự khác nhau của mỗi giải thuật, việc gán cho nó một key để định danh và đảm bảo rằng các component đều ở đúng vị trí của nó, tối ưu hóa việc rendering.

var App = React.createClass({
    getInitialState: function(){
        return {
            todos: ["eat","code","sleep"] 
        }
    },
    render: function(){
        var todos = this.state.todos.map(function(todo,index){
            return <li key={index}>{todo}</li>
        });             
        return (
            <div>
                <h1> Welcome to the ToDo list!</h1>
                <ul>
                    {todos}     
                </ul>
            </div>
        );
    }
});

refs và findDOMNode

Có thể sẽ muốn tiếp cận cây DOM, và làm một số thay đổi, nhưng không cần thiết phải sử dụng state hay là props. Trong những tình huống như thế này, bạn sẽ cần lấy các node như mong muốn. React cung cấp cho bạn một cách thủ công để có thể lấy DOM node. Đơn giản bạn gọi phương thức React.findDOMCode(component), và truyền vào component mà bạn mong muốn. Để lấy được tham chiếu của component đã chọn bạn có thể sử dụng thuộc tính refs.

<input ref={ (input) => this._input  = input } ... />

Từ đó bạn có thể tham chiếu thành phần input khai báo như trên thông qua this._input.value.

var Form = React.createClass({
  focusOnField: function(){
      React.findDOMNode(this.refs.textField).focus();
  },
  render: function(){
      return (
          <div>
              <input 
                  type="text"
                  ref="textField" />
              <input 
                  type="submit"
                  value="Focus on the input!" 
                  onClick={this.focusOnField} />
          </div>
      );
  }
});
var App = React.createClass({
  render: function(){
      return (
          <div>
              <h1> Welcome to the focus app!</h1>
              <Form />
          </div>
      );
  }
});
React.render(<App />,  document.getElementById("app"));

Kết quả của đoạn code trên là thành phần input sẽ được focus khi bạn click button.

0