Reactjs - Bài 5 - state là gì

Goal

Giới thiệu về state trong React và cách sử dụng nó.

Giới thiệu

Hãy chạy lại file props trong ví dụ trước:

https://slack-files.com/T035VUSF2-F060CUFL1-939dd508dd

Mở Google Chrome Dev Tool, và in ra các giá trị như sau:


(Click vào để mở lớn)

Ta có thể thấy,
props đóng vai trò như là IF để truyền data từ parent vào trong Component, nó được “sở hữu” bởi parent đó. Có thể coi props như một Component’s configuration.
Còn state như là một biến private của Component. Chúng ta có thể change states bằng cách gọi this.setState()
Lưu ý: trong bài trước, để thay đổi props ta phải gọi setProps từ bên ngoài Component: AvatarComponent.setProps

Ví dụ để hiểu rõ hơn state:

Ta sẽ lấy ví dụ trước và thử đưa state vào trong Component Avatar. Bởi vì state dùng cho việc thay đổi nội bộ trong Component, cho nên ta hãy xem cái gì trong nội bộ Avatar Component có thể thay đổi được một cách nội bộ.
OK, ta thử thay đổi image của avatar. Ý tưởng như sau: khi click vào button, thì image của avatar thay đổi.
Source code:
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv='Content-type' content='text/html; charset=utf-8'>
  <title>Basic Example Props</title>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js"></script>  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
  <script type="text/jsx">

    var Avatar = React.createClass({
      propTypes: {
        name: React.PropTypes.string.isRequired,
        width: React.PropTypes.number.isRequired,
        height: React.PropTypes.number.isRequired
      },

      getInitialState() {
        return {
          src: 'http://canime.files.wordpress.com/2010/05/mask-dtb.jpg'
        };
      },

      onClick() {
        this.setState({src: 'http://38.media.tumblr.com/9f96b52d8fda03c77d0b620d4f12a128/tumblr_n0lvu7fSqE1sont7fo1_500.gif'});
      },

      render() {
        //var src='http://canime.files.wordpress.com/2010/05/mask-dtb.jpg';
        return (
          <div>
            <img  src={this.state.src} width={this.props.width} height={this.props.height} alt="alt" />
            <span>{this.props.name}</span>
            <button onClick={this.onClick}>So HOT!!!!</button>
          </div>
        );
      }

    });


    var AvatarEl = <Avatar name="Foo" width={100} height={100}/>;

    var AvatarComponent = React.render(AvatarEl, document.body);


  </script>
</body>
</html>
Hãy thử chạy file source trên, click vào button, bạn có thấy image của avatar đã thay đổi!
Về cơ bản cấu trúc một Component có state như sau:
  1. method render()
  2. method getIntialState(): initial giá trị state cho Component. Trong ví dụ trên, chúng ta initial giá trị src của statehttp://canime.files.wordpress.com/2010/05/mask-dtb.jpg
  3. method handle Event: đây là method dùng để handle sự kiện trong Component. Hay cũng chính là callback function của event. Trong ví dụ trên, khi có sự kiện click thì nó thực thi method onClick() thay đổi image source của avatar.
  4. this.setState: được gọi trong method onClick, sẽ thay đổi data trong Component -> trigger render -> rerender View của Component.

Sự giống nhau propsstate

  • propsstate đều là plain JS objects
  • propsstate đều trigger render update khi thay đổi

Sự khác nhau propsstate

Features props state
Can get initial value from parent Component? Yes Yes
Can be changed by parent Component? Yes No
Can set default values inside Component?* Yes Yes
Can change inside Component? No Yes
Can set initial value for child Components? Yes Yes
Can change in child Components? Yes No

Reactjs - Bài 4 - props là gì

Goal

Giới thiệu props và làm sao sử dụng nó.

Giới thiệu

Trong bài trước, chúng ta đã có dịp tiếp xúc với props, khi dùng nó để truyền giá trị name là ‘Phúng’ vào trong.
Vậy props là gì? Nó đóng vai trò như thế nào trong React Component?

props là gì

props là một attribute của Component. Chúng ta có thể sử dụng props như là một Object hay là một Function

props đóng vai trò gì

props chứa giá trị được chuyển từ bên ngoài vào trong Component.

PropTypes

Khi bạn muốn validate props, hãy sử dụng PropTypes để làm việc đó.
var Avatar = React.createClass({
  propTypes: {
    name:   React.PropTypes.string.isRequired,
    id:     React.PropTypes.number.isRequired,
    width:  React.PropTypes.number.isRequired,
    height: React.PropTypes.number.isRequired,
    alt:    React.PropTypes.string
  },
  render() {
    var src = `/img/avatar/${this.props.id}.png`;
    return (
      <div>
      <img src={src} width={this.props.width} height={this.props.height} alt={this.props.alt} />
      <span>{this.props.name}</span>
      </div>
    );
  }
});
<Avatar name="foo" width={100} height={100} />

Default Prop value

React cung cấp cho bạn cách define default valuse cho props rất rõ ràng
var Hello = React.createClass({
  getDefaultProps() {
    return {
      name: "React"
    };  
  },
  render() {
    return <div>Hello {this.props.name}</div>
  }
});

setProps và replaceProps

Khi bạn gọi setProps(), nó sẽ thay đổi properties của Component và trigger một re-render. Ngoài ra, bạn cũng có thể đưa vào một callback function mà sẽ được thực thi một khi setProps được hoàn thành.
Hãy thử chạy ví dụ sau
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv='Content-type' content='text/html; charset=utf-8'>
  <title>Basic Example Props</title>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js"></script>  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
  <script type="text/jsx">

    var Avatar = React.createClass({
      propTypes: {
        name: React.PropTypes.string.isRequired,
        width: React.PropTypes.number.isRequired,
        height: React.PropTypes.number.isRequired
      },
      render() {
        var src='http://canime.files.wordpress.com/2010/05/mask-dtb.jpg';
        return (
          <div>
            <img src={src} width={this.props.width} height={this.props.height} alt="alt" />
            <span>{this.props.name}</span>
          </div>
        );
      }

    });


    var AvatarEl = <Avatar name="Foo" width={100} height={100}/>;

    var AvatarComponent = React.render(AvatarEl, document.body);

  </script>
</body>
</html>
Bây giờ, ta thử thay đổi các properties name của AvatarComponent ở trên bằng cách thêm đoạn code sau:
    AvatarComponent.setProps({name: "Bar"}, function(){
      alert("AvatarComponent setProps Done!");
    });
Sau đó, bạn thử refresh lại trang tên của Avatar giờ thành ‘Bar’, và sau khi setProps() hoàn thành thì nó thực thì callback function là alert string “AvatarComponent setProps Done!”.
Bây giờ, ta thử dùng replaceProps() để thay đổi properties name của AvatarComponent ở trên bằng cách thêm đoạn code sau:
    AvatarComponent.replaceProps({name: "Bar-Foo"}, function(){
      alert("AvatarComponent replaceProps Done!");
    });
Bạn có thấy điều gì khác giữa setProps()replaceProps() không?
Với setProps() nó merge property nào mà nó set.
Với replaceProps() nó delete các props tồn tại trước đó và thay bởi properties mới.

Reactjs - Bài 3 - JSX là gì

GOAL

Giới thiệu về JSX.

JSX là gì

JSX = Javascript + XML.

Thử một ví dụ JSX đơn giản

Hãy quay trở lại ví dụ trong bài giới thiệu ‘Hello World’, phần 1.
    <script>
      var helloEl = React.createElement('div', { className: 'hello' }, 'Hello, world!');
      React.render(
          helloEl,
          document.body
      );
    </script>
Bây giờ ta thử viết lại theo syntax JSX
    <script type="text/jsx">
      var helloEl = <div className: "hello">Hello, world!</div>;
      React.render(
          helloEl,
          document.body
      );
    </script>
Bây giờ bạn thử chạy source code sau:
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv='Content-type' content='text/html; charset=utf-8'>
  <title>Basic Example Hello world</title>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js"></script>  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
  <script type="text/jsx">
    var helloEl = <div className="hello">Hello, World!</div>
    React.render(
        helloEl,
        document.body
    );
  </script>
</body>
</html>
Có phải là nó cũng hiển thị ra trang HTML giống như ví dụ trước không? Đó là nhờ vào React JSX. React JSX sẽ transform XML-like syntax thành Javascript. Các XML elements, attributes và children được chuyển đổi thành các đối số truyền vào React.createElement.
//Input (JSX)
var helloEl = <div className: "hello">Hello, world!</div>;

//Output (JS)
var helloEl = React.createElement('div', { className: 'hello' }, 'Hello, world!');

HTML Tags vs. React Components

React có thể render HTML tags (dạng string) hay React components.
Để render một HTML tag, chỉ cần sử dụng tên bằng chữ viết thường trong JSX.
ở trên là một ví dụ.
Để render một React Component, chỉ cần tạo một biến local bắt đầu bằng chữ cái viết Hoa.
Ví dụ:
var Nav;

// Input (JSX)
var app = <Nav color="blue" />;

// Output (JS)
var app = React.createElement(Nav, {color:"blue"});
JSX cũng cho phép chỉ định children sử dụng XML syntax:
var Nav, Profile;
// Input (JSX):
var app = <Nav color="blue"><Profile>click</Profile></Nav>;

// Output (JS):
var app = React.createElement(
  Nav,
  {color:"blue"},
  React.createElement(Profile, null, "click")
);
Về JSX còn có những phần thú vị khác như Namespaced Components, JavaScript Expressions v.v.. tại link bên dưới:
https://facebook.github.io/react/docs/jsx-in-depth.html
Một số link tham khảo khác:
JSX Compiler
https://facebook.github.io/react/jsx-compiler.html

Hello again

Quay trở lại ví dụ Hello world trong phần 2, chúng ta thử thay đổi code theo JSX syntax
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv='Content-type' content='text/html; charset=utf-8'>
  <title>Basic Example Hello world</title>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js"></script>  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
  <script type="text/jsx">

    var HelloComponent = React.createClass({
      render: function() {
        return <div className="hello">Hello, {this.props.name}</div>
      }
    })
    var helloEl = <HelloComponent name=' Phúng' />;

    React.render(
        helloEl,
        document.body
    );

  </script>
</body>
</html>
  • Lưu ý: như phần trên đã nêu, để render một React Component, thì tên Component đó phải bắt đầu bằng ký tự in hoa. Do đó ở đây helloComponent trở thành HelloComponent

JSX and ES6

Nhờ vào JSX Transform mà chúng ta có một vài features trong ES6 như Arrow functionConcise methods
  1. Arrow function: đặt biệt hữu ích khi kết hợp với mapfilter methods (Chúng ta sẽ có dịp trải nghiệm trong các bài viết sau)
  2. Concise methods: chúng ta sẽ không còn cần cách viết : function trong object nữa.
Do đó, chúng ta có thể:
Viết theo cách cũ
  render: function() {
    return <div className="hello">Hello, {this.props.name}</div>
  }
Viết theo cách mới
  render() {
    return <div className="hello">Hello, {this.props.name}</div>
  }

Reactjs - Bài 2 - Helloworld - phần 2 - React Component

Dẫn nhập

Trong phần 1, chúng ta đã dùng React.creatElement để tạo ReactElement và dùng React.render để render ReactElement và gắn vào Real DOM để hiển thị lên trang web. Trong phần 2 này, tôi muốn giới thiệu về ReactComponent.
Cũng cần nói thêm ReactElement thuộc thành phần cơ bản nhất của React. Nó có 4 properties: type, props, key và ref. Nó không có methods và prototype cũng không có gì cả.
Với ReactElement cũng đủ cho bạn render một View, nhưng chúng ta sẽ không tận dung hết lợi điểm của React. Với ReactComponent, chúng ta có thể tạo một sự bao đóng với embeded state (trạng thái được nhúng).
Ví dụ, trong ví dụ ở phần 1, chúng ta render ra được nội dung ‘Hello, world’ nhưng nếu chúng ta muốn thay đổi ‘Hello, world’ thành ‘Hello, Phung’ thì sẽ không được, trừ khi chúng ta sửa lại code, thay từ ‘world’ thành từ ‘Phung’. Như vậy chúng ta chỉ có được một ‘Static UI’.
Trong khi đó nếu dùng ReactComponent thì chúng ta có thể thay đổi ‘world’ thành ‘Phung’ thông qua embeded state trong ReactComponent, do đó chúng ta có thể tương tác và có được một ‘Dynamic UI’. Trước mắt hãy xem state như là một đối số giúp ta có thể tương tác với UI.

Get your hand dirty

Từ ví dụ ở phần 1, chúng ta thử đưa lần lần ReactComponent vào.
Source code mẫu:
https://slack-files.com/T035VUSF2-F0559AYFY-60efc6e91b
Hãy xem helloComponent ở ví dụ trên
   var helloComponent = React.createClass({
      render: function() {
        return React.createElement('div', {className: 'hello'}, 'Hello, Phúng');
      }
    });
Format của nó như sau
var MyComponent = React.createClass({
    render: function() {
       ...
      }
    });
Khi tạo một Component Class bởi React.createClass(), ta sẽ cung cấp cho nó một object ( phần { … } ) cụ thể có chứa render method và những methods khác.
Như bạn thấy ở trên, React Component Class ở trên giống như là một Function mang theo propsstate (sẽ trình bày sau), và render HTML.
Tiếp theo là helloEl được tạo từ React Component Class
var helloEl = React.createElement(helloComponent);
Phần gắn helloEl vào document.body thì giống như đã trình bày trong phần 1.
Với những giải thích ở trên hy vọng các bạn đã có một khái niệm sơ bộ về React Component. Tiếp theo ta đưa tên ‘Phúng’ ra khỏi helloComponent và thay vào đó là đối số this.props.name sẽ được truyền vào.
Source code:
https://slack-files.com/T035VUSF2-F055Y3SUF-8b903b5e26
Trong phần này có thêm một khái niệm mới là props. props sẽ được giới thiệu chi tiết hơn trong bài viết sau, còn trong giới hạn của bài viết này tôi muốn bạn xem props như là một “model” data trong React và Component sẽ lấy data từ props và render nó.