Tìm hiểu react - part 2

Chúng ta đã tìm hiểu về một vài khái niệm cơ bản trong React ở bài trước, ở bài này chúng ta sẽ cùng tìm hiểu về cách dữ liệu di chuyển trong React.

Inverse data flow

Chúng ta đã nói về việc làm thế nào luồng dữ liệu chỉ có một chiều trong React, từ cha đến con. Thật ra điều này không hoàn toàn đúng, vẫn có cách để thêm một dòng dữ liệu theo hướng ngược lại. Đó chính là Inverse data flow.

Ta cần đế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ó. Đây là một bài toán khá cơ bản.

Dưới đây là một 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ó, cũng như việc có thể 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ó.

refs và findDOMNode

Thỉnh thoảng, bạn 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.

Thật may mắ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. Đơn giản thêm một ref vào trong phần tử như thế này.

<input ref="textField" ... />

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

Ví dụ.

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.

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.

Như thế này.

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>
        );
    }
});