TÌm hiểu React

I. Giới thiệu

  • Là một thư viện Javascript cho phép xây dựng nên giao diện người dùng
  • Nó chỉ là UI ( giao diện người dùng), nó tương ứng với phần V trong mô hình MVC
  • Sử dụng Virtual Dom để xử lý việc thay đổi trạng thái của các thành phần

II. Các thành phần trong React

II.1. Props

  • Được sử dụng để truyền dữ liệu vào trong React view. Bất kỳ sự thay đổi nào từ prop rerender view sẽ được kích hoạt, những sự thay đổi này có thể là các bản thân view component hay parent view component hay child view component. Nó cho phép truyền dữ liệu giữa các view component với nhau một cách đồng bộ.
  • Props được sử dụng để truyền dữ liệu giữa các class con và class cha của React, bất cứ sự thay đổi nào của prop sẽ tự động kích hoạt rerender view, đối với cả thành phần cha và con.
var HelloWorld = React.createClass({
    render: function() {
        return <div>Hello! {this.props.name}!</div>;
    }
});
React.render(<HelloWorld name='Teo'/>,document.body);

Name Teo sẽ được in ra trong thẻ div

Hello! Teo!

II.1.1. Prop validation

React sử dụng propType cho việc validate dữ liệu của component. React cung cấp khá nhiều validation để đảm bảo dữ liệu được valid, khi một giá trị không hợp lệ được gán cho prop thì sẽ có cảnh báo xuất hiện ở Javascript console. Ví dụ


var ValidateComponent =
React.createClass({
  propTypes: {
    name: React.PropTypes.string.isRequired,
    age: React.PropTypes.number.isRequired
  },
  render(){
    return(
    <div> age: {this.props.age} name: {this.props.name} </div>

  );
  }
});
 React.render(<ValidateComponent age={2} name='Peter'/>, document.body)

https://jsbin.com/tutaxonoye/edit?html,js,output

Dưới đây là các kiểu validate mà React hỗ trợ:

React.createClass({
  propTypes: {
    // You can declare that a prop is a specific JS primitive. By default, these
    // are all optional.
    optionalArray: React.PropTypes.array,
    optionalBool: React.PropTypes.bool,
    optionalFunc: React.PropTypes.func,
    optionalNumber: React.PropTypes.number,
    optionalObject: React.PropTypes.object,
    optionalString: React.PropTypes.string,

    // Anything that can be rendered: numbers, strings, elements or an array
    // (or fragment) containing these types.
    optionalNode: React.PropTypes.node,

    // A React element.
    optionalElement: React.PropTypes.element,

    // You can also declare that a prop is an instance of a class. This uses
    // JS's instanceof operator.
    optionalMessage: React.PropTypes.instanceOf(Message),

    // You can ensure that your prop is limited to specific values by treating
    // it as an enum.
    optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),

    // An object that could be one of many types
    optionalUnion: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number,
      React.PropTypes.instanceOf(Message)
    ]),

    // An array of a certain type
    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),

    // An object with property values of a certain type
    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),

    // An object taking on a particular shape
    optionalObjectWithShape: React.PropTypes.shape({
      color: React.PropTypes.string,
      fontSize: React.PropTypes.number
    }),

    // You can chain any of the above with `isRequired` to make sure a warning
    // is shown if the prop isn't provided.
    requiredFunc: React.PropTypes.func.isRequired,

    // A value of any data type
    requiredAny: React.PropTypes.any.isRequired,

    // You can also specify a custom validator. It should return an Error
    // object if the validation fails. Don't `console.warn` or throw, as this
    // won't work inside `oneOfType`.
    customProp: function(props, propName, componentName) {
      if (!/matchme/.test(props[propName])) {
        return new Error('Validation failed!');
      }
    }
  },
  /* ... */
});

II.1.2. Default Prop Values

React cho phép định nghĩa giá trị default cho prop

var ComponentWithDefaultProps = React.createClass({
  getDefaultProps: function() {
    return {
      value: 'default value'
    };
  },
  render(){
    return <div>{this.props.value} </div>
  }
});
React.render(<ComponentWithDefaultProps />, document.body)

https://jsbin.com/tutaxonoye/edit?html,js,output

Giá trị của hàm getDefaultProps() sẽ được cache lại để đảm bảo this.props.value luôn luôn có giá trị

II.2. State

  • Thuộc tính state của React class cho phép chúng ta theo dõi được sự thay đổi bên trong view.
  • Nó cũng giống như props, sẽ kích hoạt rerender view bất cứ khi nào state thay đổi nhưng với một điều kiện đó là bạn phải gọi setState method, nếu như không gọi method đó thì bất cứ sự thay đổi nào của state sẽ không được thay đổi view.
  • Phải sử dụng function getInitialState khi dùng internal state, để cho view biết state sẽ được khởi tạo với giá trị nào
	getInitialState: function() {
        return {
            counter: 10
        };
    }

II.3 Sự khác nhau giữa props và state

  • Thành phần mà cần phải thay đổi thuộc tính của nó ở một vài thời điểm nào đó, thì nên sử dụng state cho các thuộc tính đó. Ngược lại thì sử dụng prop cho thành phần đó.
props state
Có thể lấy giá trị khởi tạo từ thành phần cha
Có thể được thay đổi bởi thành phần cha Không
Có thể gán giá trị mặc định bên trong thành phần
Có thể thay đổi bên trong bản thân thành phần Không
Có thể gán giá trị khởi tạo cho các thành phần con
Có thể thay đổi bên trong thành phần con Không
  • Một chú ý đó là cả propsstate đều nhận giá trị khởi tạo từ thành phần cha và được ghi đè giá trị khởi tạo định nghĩa trong component.

II.4. Nested view

  • Nesting view là việc chúng ta có thể render React class bên trong một React class khác.
var Btn = React.createClass({
    render: function() {
        return <button onClick={this.props.onClick}>
            <span>{this.props.text}</span>
        </button>
    }
});

var WrapBtn = React.createClass({
    getInitialState: function() {
        return {
            counter: 10
        };
    },

    increment: function() {
        this.setState({ counter: this.state.counter +=5});
    },

    render: function() {
        return <div>
            <div>{this.state.counter}</div>
            <Btn text="Touch me!" onClick={this.increment} />
        </div>;
    }
});

React.render(<WrapBtn />, document.body)

nested view https://jsbin.com/laroqivopu/1/edit?html,js,output

Ví dụ trên cho thấy Btn được render bên trong WrapBtn

References

Bài viết trên được tham khảo từ nguồn:

https://facebook.github.io/react/index.html

https://jsbin.com

https://github.com/uberVU/react-guide/blob/master/props-vs-state.md