+2

Bắt đầu với Reactjs- Phần 1: Tiếp cận với ReactJS. Component đầu tiên.

ReactJS là gì?

  • React.JS là một thư viện Javascript dùng để xây dựng giao diện người dùng. Nó chưa phải là 1 frameworks hoàn chỉnh. React chỉ là một library tập trung vào việc giải quyết các vấn đề ở view layer.
  • React khuyến khích việc sử dụng các Javascript API thông thường hơn là những framework abstraction.
  • Một điều làm cho React đặc biệt hơn so với các library hay framework về Javascript khác là nó cổ vũ việc đem HTML nhúng vào Javascript hơn là đưa JS vào HTML.

1. Component là gì?:

  • Trong React, chúng ta xây dựng trang web sử dụng những thành phần (component) nhỏ. Chúng ta có thể tái sử dụng một component ở nhiều nơi, với các trạng thái hoặc các thuộc tính khác nhau, trong một component lại có thể chứa thành phần khác. Mỗi component trong React có một trạng thái riêng, có thể thay đổi, và React sẽ thực hiện cập nhật component dựa trên những thay đổi của trạng thái của dữ liệu.
  • React sử dụng khái niệm DOM ảo (Virtual DOM) để chọn lựa và render những phần tử của node dựa tên sự thay đổi trạng thái khiến cho ta chỉ cần thay đổi ít thành phần nhất có thể để giữ DOM update.
  • Ở đây React sẽ tạo một DOM ảo (Virtual DOM) từ DOM, tất cả các thao tác sẽ được thực hiện trên DOM ảo trước, tiếp theo thì nó sẽ so sánh sự khác biệt để phát hiện ra thay đổi rồi chỉ cập nhật DOM.
  • Qua hình ảnh trên chúng ta còn có thể thấy. React xây dựng cấu trúc data theo 1 chiều. Nghĩa là sẽ có 1 "Cha" ôm toàn bộ data, và "Con" sẽ sử dụng dữ liệu của "Cha" mà sẽ không thay đổi nó. Từ đó phát sinh một số vấn đề ví dụ như sẽ có những component mang vai trò "Cha" chứa data và sẽ có những component chỉ quan tâm đến data nó nhận được và dựa vào đó render view, 2 loại component này sẽ là 1 vấn đề đáng quan tâm của react mà tôi sẽ nói đến bên dưới đây Stateful component vs Stateless component.
  • 1 cách cụ thể bạn có thể tham khảo tài liệu chính thức tại đây để hiểu rõ hơn về component.
import React, {Component, PropTypes} from 'react';

class Example extends Component {
  constructor(props){
    super(props)
    // Hàm này Thực hiện việc thiết lập state cho component
    // Việc sử dụng super(props) là để có thể sử dụng this.props trong phạm vi hàm constructor này
  }
  
  componentWillMount() {
    // Thực hiện một số tác vụ, hàm này chỉ thực hiện 1 lần duy nhất
    
  }
  componentDidMount() {
    // Thực hiện một số tác vụ, hàm này chỉ thực hiện 1 lần duy nhất
    // Hàm này rất hữu dụng khi bạn làm việc thêm với Map, bởi vì map chỉ render được 
    // khi có node (id) trong DOM  
    // Nói tóm lại, hàm này được gọi để thông báo component đã tồn tại trên DOM, 
    // từ đó các thao tác trên DOM sẽ có thể thực hiện bình thường đối với component này
  }
  componentWillUnmount() {
    // Hàm này thực hiện một lần duy nhất, khi component sẽ unmount
    // Hàm này hữu dụng khi bạn cần xoá các timer không còn sử dụng
  }
  componentWillReceiveProps(nextProps) {
    // Hàm này thực hiện liên tục mỗi khi props thay đổi
    // (1) Sử dụng để thay đổi trạng thái (state) của component phụ thuộc props
    // (2) Sử dụng các kết quả, khởi tạo biến có tính chất async. Ví dụ: Khởi tạo Google Map Api, đây là quá trình async,
    // do vậy, bạn không thể biết được khi nào khởi tạo xong, thì khi khởi tạo xong có thể truyền xuống component thông qua
    // props, và từ đó bạn có thể khởi tạo các dịch vụ khác.
    // Code mẫu:
    //# if(nextProps.mapLoaded){ //props.mapLoaded khởi tạo false
    //#     let googleMaps = this.props.googleMaps ||
    //#         (window.google && // eslint-disable-line no-extra-parens
    //#         window.google.maps) ||
    //#         this.googleMaps;

    //#     if (!googleMaps) {
    //#         console.error(// eslint-disable-line no-console
    //#          'Google map api was not found in the page.');
    //#         return;
    //#     }
    //#     this.googleMaps = googleMaps;

    //#     this.autocompleteService = new googleMaps.places.AutocompleteService();
    //#     this.geocoder = new googleMaps.Geocoder();
    //# } 
  }
  shouldComponentUpdate(nextProps, nextState) {
    // Hàm này thực hiện khi state và props thay đổi
    // Hàm này sẽ trả về kết quả true/false, bạn sẽ cần sử dụng đến hàm này để xử lý xem có cần update component không
  }
  
  componentWillUpdate(nextProps, nextState) {
    // Hàm này thực hiện dựa vào kết quả của hàm trên (shouldComponentUpdate)
    // Nếu hàm trên trả về false, thì React sẽ không gọi hàm này
  }  
  componentDidUpdate(prevProps, prevState) {
    // Hàm này thực hiện sau khi component được render lại, từ kết quả của componentWillUpdate
  }
  
  render() {
    return (
      <div>
        // thực hiện việc render
      </div>
    );
  }
}

Example.propTypes = {
  //Khai báo kiểu biến cho props
};
Example.defaultProps = {
  //Khai báo giá trị mặc định cho props
}
export default User;

Vòng đời của component Khởi tạo Component

Lần lượt các hành động sau để khởi tạo component:

Khởi tạo Class (đã thừa kế từ class Component của React) Khởi tạo giá trị mặc định cho Props (defaultProps) Khởi tạo giá trị mặc định cho State (trong hàm constuctor) Gọi hàm componentWillMount() Gọi hàm render() Gọi hàm componentDidMount() Khi State thay đổi

Cập nhật giá trị cho state Gọi hàm shouldComponentUpdate() Gọi hàm componentWillUpdate() – với điều kiện hàm trên return true Gọi hàm render() Gọi hàm componentDidUpdate() Khi Props thay đổi

Cập nhật giá trị cho props Gọi hàm componentWillReceiveProps() Gọi hàm shouldComponentUpdate() Gọi hàm componentWillUpdate() – với điều kiện hàm trên return true Gọi hàm render() Gọi hàm componetDidUpdate() Khi Unmount component

Gọi hàm componentWillUnmount()

2 . Props & State

  • Có hai kiểu của data trong React đó là props và state.
  • Ngắn gọn thì ta có thể hiểu:
    • Props: là dữ liệu component nhận được từ component "Cha" và nó không có thể tự thay đổi.
    • State: là dữ liệu mà component nắm dữ và quyết định giá trị của nó.
  • Cụ thể hơn thì điểm mấu chốt 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 xong tất nhiên điều này có thể làm một cách gián tiếp bằng cách "Con" sẽ nói với "Cha"-"Con" muốn thay đổi data như thế nào, thì nó có thể tự thay đổi state của bản thân.
  • Trong React, bạn chỉ khởi tạo giá trị this.state một lần duy nhất, sau khi khởi tạo xong, nếu bạn muốn cập nhật this.state, bạn phải dùng hàm this.setState.
  • Khi sử dụng this.setState, chính là kích hoạt danh sách các phương thức thuộc vòng đời của component (shouldComponentUpdate, componentWillUpdate, render, componentDidUpdate). Và cũng luôn nhớ rằng, this.setState là hàm async, nên truy cập this.state ngay sau khi setState sẽ không nhận được giá trị mới của this.state.

3. Bắt đầu với ReactJS.

Cài đặt:

ReactJS không phải là 1 framework đầy đủ mà chỉ là 1 library hỗ trợ view layer nên khi sử dụng ReactJS 1 cách riêng biệt thì bạn cần phải thực sự quan tâm đến xây dựng cấu trúc dự án. Đặt biệt khi làm việc trong 1 team. Để bắt đầu chúng ta sẽ tạm quên việc này mà sẽ học hỏi dần qua cấu trúc được xây dựng nhờ create-react-app. Chúng ta có 1 thư mục với cấu trúc như sau:
1. package.json: sẽ ghi lại các package mà chúng ta sử dụng. 2. nodemodules: là thư mục cài đặt các package mà chúng ta sử dụng, nó là thành phần giúp ứng dụng của chúng ta hoạt động. 3. src: Đây sẽ là toàn bộ sources code của chúng ta, và đương nhiên public mang đầy đủ nghĩa của nó rồi.

  • public/index.html: Đây sẽ là SPA của chúng ta. src/index.js: Chúng ta bắt đầu với react ở đây. Render component* App* src/App.js: Theo cách gọi của index.js Đây sẽ là root component, nơi khởi đầu của ứng dụng react chúng ta đang xây dựng. Để start chúng ta dùng lệnh: npm start

Hello world!

Theo cá nhân thì mình thích tổ chức lại các thư mục 1 tí: Đưa tất cả components vào 1 thư mục components :

mkdir -p src/components/App mv src/App.js src/components/App/index.js mv src/App.css src/components/App/style.css mv src/logo.svg src/components/App/logo.svg Tại /src/index.js:

// Change import path
import App from './App';
// To
import App from './components/App'; 

1.Tạo component HelloWorld:

mkdir src/components/HelloWorld touch src/components/HelloWorld/index.js touch src/components/HelloWorld/style.css

  1. src/components/HelloWorld/index.js
import React from 'react';

const HelloWorld = () => {
    return (
        <h1>Hello, world!</h1>
    );
};

export default HelloWorld;

3.src/components/App/index.js Tiện thể chúng taedit lại App thành Stateless component

import React, { Component } from 'react';

import logo from './logo.svg';
import './style.css';
import HelloWorld from './../HelloWorld';

const App =() => {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>My First React Application</h2>
        </div>
        <p className="App-intro">
          <HelloWorld />
        </p>
      </div>
    );
  }
}

export default App;
  1. Xem kết quả của chúng ta nào:
  2. Bắt đầu với 1 ví dụ với props nhé:

mkdir src/components/Welcome touch src/components/Welcome/index.js touch src/components/Welcome/style.css

  1. *src/components/Welcome/index.js *:
import React from 'react';

const Welcome = (props) => (
   <h1>Welcome, {props.name} </h1>
);

export default Welcome;
  1. src/components/App/index.js
import React, { Component } from 'react';

import logo from './logo.svg';
import HelloWorld from './../HelloWorld';
import Welcome from './../Welcome';
import './style.css';

const App =() => {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>My First React Application</h2>
        </div>
        <p className="App-intro">
          <HelloWorld />
          <Welcome name="Tee" />
        </p>
      </div>
    );
  }
}

export default App;
<!--Truyền 1 props *name* đến cho component Welcome -->   
<Welcome name="Tee" />
<!--chúng ta truy vấn *name* từ props của component bằng cách  -->   
{props.name}

Kết quả:

4. Kết luận:

Vậy là chúng ta đã đi qua vài khái niệm cơ bản về hệ sinh thái React. Mình sẽ làm rõ hơn về data follow của react cũng như chỉ ra quan hệ và khác biệt của Stateful component vs Stateless component.

Để hiểu hơn về component và props. Bạn nên đọc thêm tại: https://facebook.github.io/react/docs/components-and-props.html Thời gian mình tìm hiểu về ReactJS là chưa nhiều, nếu còn thiếu sót, mình rất mong nhận được sự góp ý của các bạn.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí