Tìm hiểu react - part 1

ReactJS là gì?

React.JS là một thư viện Javascript dùng để xây dựng UI. React đơn thuần chỉ phục vụ cho tầng View (V trong mô hình MVC). Theo như nhận xét chung của cộng đồng về ReactJS thì nó nhanh và dễ học. React thường được so sánh với vai trò tương đương như các Javascript framework khác như Angular chẳng hạn. Nhưng đây là một sự so sánh khập khiễng bởi chúng sinh ra để đảm nhiệm những vai trò khác nhau. Angular là một framework hoàn chỉnh còn React thì không, React thường được tích hợp trong một hệ sinh thái gồm các framwork hoàn chỉnh để phục vụ cho tầng view. React cung cấp cho bạn một ngôn ngữ tạo template và các function nhằm render ra các mã HTML và đó cũng là tất cả những gì mà React có thể output ra. Các đoạn mã HTML/Javascript được gọi là các "Component" nếu có khả năng lưu trữ các trạng thái của chính nó trong bộ nhớ, nhưng cuối cùng chúng cũng chỉ sinh ra mã HTML mà thôi.

Tiếp theo chúng ta sẽ đến với những khái niệm cơ bản.

Component

React được xây dựng xung quanh các component, chứ không dùng template như các framework khác. Bạn có thể tạo ra một component bằng các gọi phương thức createClass của đối tượng React, đây là điểm bắt đầu khi tiếp cận với thư viện này. Ví dụ.

var Button = React.createClass({
    render: function(){
        return (
            <input type="submit" />
        );
    }
});

Phương thức 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. Ví dụ ở trên đơn giản là 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ẽ take care việc update UI với dữ liệu tương ứng. Hiểu đơn giản là, khi dữ liệu thay đổi React sẽ tự động gọi hàm render để update lại UI.

JSX — Javascript Syntax Extension

Đây đơn giản là một syntax extension của Javascript. Với nó bạn có thể viết Javascript với những tag giống như XML. Về bản chất, các tag thực sự là những lời gọi hàm, sẽ được chuyển đổi trong React code và end up dưới dạng HTML và Javascript trong cây DOM. Hãy hiểu đơn giản nó giống như là HTML/XML với một số khả năng khác.

Multiple components

Nếu bạn 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. Ví dụ.

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

Phía trên, tôi đang lồng Form component vào trong App component. Đây là một dạng quan hệ cha con (parent-child) mà bạn có thể dễ dàng nhận thấy trong HTML. Phương thức React.render() như các bạn thấy ở trên nhằm mục đích kickstart 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

Có hai kiểu của data trong React đó là props và state. Sự khác biệt giữa hai kiểu thì hơi khó khăn để hiểu ngay từ ban đầu. Điểm mấu chốt của sự khác nhau ở đây 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 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 mà phải thực hiện một cách gián tiếp, thì nó có thể tự thay đổi state của bản thân.

Props

Cùng xem xét kỹ hơn về props, cũng như hiểu về data flow một chiều trong React, điều này vô cùng quan trọng. Đầu tiên ta cần lấy dữ liệu từ một nơi nào đó. Đó có thể là Ajax call để lấy một số dữ liệu từ API, tuy nhiên để cho ví dụ được đơn giản chúng ta sẽ hard code nó như một variable.

var text = "Click the button";

Cách để đưa props vào một component tương tự cách mà chúng ta khai báo attribute cho một HTML element.

<App text={text} />

Lý do chúng ta sử dụng cặp ngoặc nhọn là vì chúng ta cần nói cho JSX biết rằng đó là một Javascript expression. 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. Từ góc nhìn của component, props của nó là bất biến (immutable). Nó chỉ là thông tin được cài đặt cho component. Ví dụ.

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

Như các bạn thấy, 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 để storing dữ liệu trong React là state. Không giống như props, bất biến duới góc nhìn của component thì state có thể thay đổi (mutable). 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, đơ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, đơn giản ta gọi hàm this.setState(), và truyền vào state mới như là một tham số. Ví dụ.

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 cũng cho bạn làm quen với hệ thống event trong React. Chúng ta hook một event listener vào trong button, ở trên là onClick. 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.

Chú ý: React event được wrap để chạy trên tất cả các browser, có nghĩa là React giúp bạn đảm bảo event của bạn chạy được trên tất cả các trình duyện.

Chúng ta nên giữ state ở đâu? Để hình dung việc state được giữ ở đâu, bạn hãy hỏi bản thân một vài câu hỏi, những câu hỏi này được lấy từ React docs:

  • 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)
  • Hoặc là những component là chủ sở hữu chung hoặc là những component nằm trên hệ thống phân cấp sẽ nên giữ 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