Component trong React

Component trong React

Rate this post

React là một thư viện dựa trên JavaScript phổ biến được sử dụng để xây dựng giao diện người dùng với cách tiếp cận kiến ​​trúc dựa trên component.

Component trong ReactJS là gì?

Mỗi ứng dụng React chứa các component đại diện cho các màn hình hoặc phần tử cụ thể trong ứng dụng. Các component là một trong những khối xây dựng cơ bản của React và chúng đại diện cho các lớp hoặc hàm chấp nhận đầu vào và hiển thị các phần tử HTML khác nhau.

Trong hướng dẫn này, bạn sẽ tìm hiểu cách các component được sử dụng trong một ứng dụng React và xem xét các ví dụ khác nhau, bao gồm các component dựa trên lớp và các component chức năng.

Các bài viết liên quan:

Tạo một component đơn giản

Trong React, bạn không cần phải tạo một lớp hoặc component dựa trên chức năng với các dòng mã chỉ để in “Hello World”. component có thể được tạo bằng cú pháp ES6 trong một dòng, như sau:

const HelloWorld = () => <div>This is single line component</div>;

Trong ví dụ này, hàm mũi tên ES6 đã được sử dụng. Đây là component nhỏ nhất mà chúng tôi có thể tạo cho một ứng dụng React.

Truy cập component như thế này:

import React, { Component } from "react";
import { render } from "react-dom";

const HelloWorld = () => <div>This is single line component</div>;

class App extends Component {
  constructor() {
    super();
  }

  render() {
    return (
      <div>
        // Accessed the component
        <HelloWorld />
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

Trong ví dụ trên, component được tạo trong cùng một tệp và được sử dụng trong hàm render () dưới dạng <HelloWorld />. Vì vậy, khi bạn chạy ví dụ này, đầu ra sẽ là chuỗi tĩnh.

Tạo component dựa trên lớp

Trong React, một component cũng có thể được viết bằng cú pháp các lớp ES6, như trong ví dụ trên, bằng cách sử dụng hàm mũi tên.

Các component dựa trên lớp là một cách tiếp cận được sử dụng rộng rãi để tạo các component trong React nếu một ứng dụng yêu cầu trạng thái được sử dụng.

Tạo một component dựa trên lớp như thế này:

import React, { Component } from "react";

class ClassComponent extends Component {
  render() {
    return <div>This is simple class based component</div>;
  }
}

export default ClassComponent;

Như bạn có thể thấy trong ví dụ trên, component đang được nhập từ gói react, cho phép chúng ta chuyển đổi lớp thành component bằng cú pháp ES6.

Ngoài từ khóa component, tệp còn có một phần bổ sung được gọi là render (), đây là hàm được sử dụng để hiển thị các phần tử HTML khác nhau vào DOM sau khi logic nghiệp vụ đã được triển khai.

Bạn có thể nhúng một component con dựa trên lớp khác vào bất kỳ component dựa trên lớp nào như được giải thích trong ví dụ bên dưới.

import React, { Component } from "react";

class ClassComponent extends Component {
  render() {
    return (
      <ChildComponent1 />
      <ChildComponent2 />
      <ChildComponent3 />
    );
  }
}

export default ClassComponent;

Trong ví dụ này, tất cả các component con này có thể là các component dựa trên lớp hoặc dựa trên chức năng và có thể được hiển thị bên trong component mẹ, được gọi là ClassComponent.

Tạo một component dựa trên chức năng

Bạn cũng có thể tạo một component trong React bằng cách sử dụng phương pháp dựa trên hàm, sử dụng hàm JavaScript bình thường.

Để sử dụng một component dựa trên hàm, hãy xuất hàm bằng từ khóa export. component chức năng có thể trông như thế này:

import React from "react";

const FunctionComponent = function(props) {
  return (
    <div>
      <p>This is function based component</p>
    </div>
  );
};

export default FunctionComponent;

Như bạn có thể thấy trong ví dụ trên, một component dựa trên hàm được tạo có tên là FunctionComponent và từ return (), phần tử được trả về giống như từ một component dựa trên lớp.

Một điều cần chú ý trong ví dụ là hàm mũi tên đã được sử dụng để tạo component; do đó, chúng tôi cũng có thể sử dụng chức năng từ khóa, như được giải thích bên dưới.

import React from 'react';

function FunctionComponent(props) {
  return (
    <div>
      <p>This is function based component</p>
    </div>
  );
}

export default FunctionComponent;

Chọn một trong các tùy chọn ở trên để tạo một component dựa trên chức năng có thể được xuất và sử dụng vào các component khác.

Components lồng nhau

Phần lớn ReactJS cho phép các components lồng vào nhau. Cho 2 components sau:

var React = require('react'); 
var createReactClass = require('create-react-class'); 
var CommentList = reactCreateClass({ 
   render: function() { 
     return ( 
     <div className="commentList"> 
     Hello, world! I am a CommentList. 
     </div> 
     ); 
   } 
});
var React = require('react'); 
var createReactClass = require('create-react-class');
var CommentForm = reactCreateClass({ 
   render: function() { 
     return ( 
     <div className="commentForm"> 
     Hello, world! I am a CommentForm. 
     </div> 
     ); 
   } 
});

Bạn có thể lồng ghép và tham chiếu đến các components đó trong định nghĩa của một component khác

var React = require('react'); 
var createReactClass = require('create-react-class'); 
var CommentBox = reactCreateClass({ 
   render: function() { 
     return ( 
     <div className="commentBox"> 
     <h1>Comments</h1> 
     <CommentList /> // đã được xác định ở trên và được sử dụng lại 
     <CommentForm /> // Same here 
     </div> 
     ); 
   } 
}); 

Nesting có thể thực hiện theo 3 cách, tất cả điều có vị trí riêng để sử dụng:

  1.  Nesting without using children( tiếp theo từ trên)
var CommentList = reactCreateClass({ 
 render: function() { 
     return ( 
     <div className="commentList"> 
     <ListTitle/> 
     Hello, world! I am a CommentList. 
     </div> 
     ); 
   } 
}); 

Đây là kiểu từ A sang B và từ B sang C

Ưu điểm:

  • Dễ dàng và nhanh chóng để tách các thành phần từ giao diện người dùng
  • Dễ dàng đưa các props down xuống children based dựa trên trạng thái của parent components

Nhược điểm:

  • Ít khả năng tái sử dụng
  • Ít khả năng hiển thị hơn vào kiến trúc thành phần

Điểm tốt nếu:

  • B và C chỉ là các thành phần trình bày
  • B phải chịu trách nhiệm về vòng đời của C

2. Lồng dùng lớp children

var CommentBox = reactCreateClass({ 
 render: function() { 
   return ( 
       <div className="commentBox"> 
       <h1>Comments</h1> 
       <CommentList> 
       <ListTitle/> // child 
       </CommentList> 
       <CommentForm /> 
       </div> 
     ); 
   } 
})

Đây là kiểu A qua B và A yêu cầu B qua C. Thêm sức mạnh cho các parent components

Ưu điểm:

  • Quản lý components lifecycle tốt hơn
  • Khả năng hiển thị tốt hơn vào kiến trúc thành phần
  • Khả năng tái sử dụng tốt hơn

Nhược điểm:

  • Ít linh hoạt trong các child components

Tốt nếu:

B nên chấp nhận tạo ra 1 cái gì đó khác với C trong tương lai hoặc ở 1 nơi khác A nên kiểm soát vòng đời của C

B sẽ render C bằng cách sử dụng this.props.children, và không có cấu trúc nào để B biết C dùng để làm gì. Vì thế B có thể làm phong phú thêm các components bằng cách đưa các prop down vào, nhưng B phải biết chính xác chúng là gì, #3 có thể có những lựa chọn tốt hơn.

  1. Lồng sử dụng props
var CommentBox = reactCreateClass({ 
   render: function() { 
     return ( 
       <div className="commentBox"> 
       <h1>Comments</h1> 
       <CommentList title={ListTitle}/> //prop 
       <CommentForm /> 
       </div> 
     ); 
   } 
}); 

Đây là kiểu A tạo ra B và B cung cấp 1 tùy chọn để A chuyển 1 thứ gì đó để tạo ra một mục đích cụ thể. Thành phần có cấu trúc hơn

Ưu điểm:

  • Thành phần như một tính năng
  • Xác nhận dễ dàng
  • Khả năng tổng hợp tốt hơn

Nhược điểm:

  • Ít linh hoạt trong các child components

Tốt nếu:

  • B có tính năng cụ thể để được xác định để soạn nội dung
  • B chỉ nên biết cách render chứ không phải là render những gì

2.4 Props

Props là 1 cách truyền thông tin vào React component, chúng có thể bao gồm nhiều loại Function- thường được gọi là callback

Trong JSX, props được truyền vào với cú pháp thuộc tính.

<MyComponent userID={123} />

Bên trong định nghĩa cho MyComponent userID bây giờ sẽ có thể truy cập được từ đối tượng props

render() { 
 return ( 
 <span>The user's ID is {this.props.userID}</span> 
 ) 
} 

Điều quan trọng là phải xác định được tất cả các prop, loại của chúng và có thể, giá trị mặc định của chúng

// được định nghĩa ở cuối MyComputer 
MyComponent.propTypes = { 
 someObject: React.PropTypes.object, 
 userID: React.PropTypes.number.isRequired, 
 title: React.PropTypes.string 
}; 
MyComponent.defaultProps = { 
 someObject: {}, 
 title: 'My Default Title' 
} 

Trong ví dụ này, prop someObject là một lựa chọn còn prop userID là một bắt buộc. Nếu bạn không cung cấp userID cho MyComputer, trong thời gian này, công cụ React sẽ hiển thị bảng điều khiển cảnh báo bạn rằng phần mềm hỗ trợ cần thiết không được cung cấp. Tuy nhiên, hãy cẩn thận, cảnh báo này chỉ được hiển thị trong phiên bản phát triển của thư viện React, phiên bản sản xuất sẽ không ghi lại bất kỳ cảnh báo nào.

Sử dụng defaultProps cho phép bạn đơn giản hóa

const { title = 'My Default Title' } = this.props; 
console.log(title); 
console.log(this.props.title); 

Nó cũng là 1 biện pháp bảo vệ để sử dụng các Object array và Functions. Nếu bạn không thêm  default prop vào trong Object, phần sau sẽ xuất hiện lỗi nếu prop không được thông qua

if (this.props.someObject.someKey)

Trong ví dụ trên this.props.someObject  là không được xác định và do đó việc kiểm tra somekey sẽ tạo ra lỗi và mã sẽ bị. Với việc sử dụng defaultProps, bạn có thể yên tâm sử dụng cách kiểm tra trên.

2.5 Components state – Giao diện người dùng

Giả sử chúng ta muốn có 1 tiêu đề( giả sử h3), và khi nhấp vào nó, chúng ta muốn nó trở thành 1 ô nhập dữ liệu để chúng ta có thể sửa đổi tên tiêu đề. React làm điều này rất đơn giản và trực quan bằng cách sử dụng các components state và các câu lệnh if..else

//Tôi sử dụng các phần tử React Bootstrap, nhưng code cũng hoạt động với các phần tử html thông thường

//Tôi sử dụng các phần tử React Bootstrap, nhưng code cũng hoạt động với các phần tử html thông thường
var Button = ReactBootstrap.Button; 
var Form = ReactBootstrap.Form;
GoalKicker.com - Ghi chú về React JS dành cho người chuyên nghiệp
var FormGroup = ReactBootstrap.FormGroup; 
var FormControl = ReactBootstrap.FormControl; 
var Comment = reactCreateClass({ 
   getInitialState: function() { 
       return {show: false, newTitle: ''}; 
   }, 
   handleTitleSubmit: function() { 
   //code xử lý input đầu vào – ví dụ, đưa ra yêu cầu ajax để thay đổi tên trong database
   }, 
   handleTitleChange: function(e) { 
   //code thay đổi tên trong ô biểu mẫu. newTitle được khởi tạo dưới dạng chuỗi trống. chúng ta cần cập nhật nó với chuỗi người dùng vừa nhập vào biểu mẫu 
       this.setState({newTitle: e.target.value}); 
   }, 
   changeComponent: function() { 
   // điều này chuyển đổi biến hiển thị cho giao diện người dùng
       this.setState({show: !this.state.show)}; 
   }, render: function() { 
     var clickableTitle; 
     if(this.state.show) { 
       clickableTitle = <Form inline onSubmit={this.handleTitleSubmit}> 
       <FormGroup controlId="formInlineTitle"> 
       	<FormControl type="text" onChange={this.handleTitleChange}>  
         </FormGroup> 
       </Form>; 
     } else { 
       clickabletitle = <div> 
       <Button bsStyle="link" onClick={this.changeComponent}>  <h3> Default Text </h3> 
       </Button> 
       </div>; 
     } 
     return ( 
       <div className="comment"> 
       {clickableTitle} 
       </div> 
     ); 
   } 
  }); 
ReactDOM.render( 
 <Comment />, document.getElementById('content') 
); 

Phần chính của mã là biến  clickableTitle. Dựa trên hiển thị của biến state, nó có thể là 1 phần tử của Form element hoặc Button element. React cho phép nesting of components.

chúng ta có thể thêm phần tử {clickableTitle} vào trong render function. Nó tìm kiếm biến  clickableTitle, dựa trên giá trị của ‘this.state.show’, nó sẽ hiển thị phần tử tương ứng.

setStat trong Componnent

Bạn nên thận trọng khi sử dụng setState trong ngữ cảnh không đồng bộ.Ví dụ: bạn có thể thử gọi setState trong lệnh callback của một yêu cầu nhận:

class MyClass extends React.Component { 
   constructor() { 
     super(); 
     this.state = { 
     user: {} 
   }; 
 } 
 componentDidMount() { 
 	this.fetchUser(); 
 } 
 fetchUser() { 
   $.get('/api/users/self') 
   .then((user) => { 
   	this.setState({user: user}); 
   }); 
 } 
 render() { 
 	return <h1>{this.state.user}</h1>; 
 } 
} 

Điều này có thể gọi là 1 sự cố, nếu lệnh callback gọi lại sau khi components được tháo xuống, thì this.setState sẽ không phải là 1 function. Bất cứ khi nào rơi vào trường hợp này, bạn nên thật cẩn thận để đảm bảo rằng việc sử dụng setState của bạn bị hủy bỏ.

Trong ví dụ này, bạn có muốn hủy bỏ XHR khi components gỡ xuống.

class MyClass extends React.Component { 
 constructor() { 
   super(); 
   this.state = { 
   user: {}, 
   xhr: null 
   }; 
 } 
 	componentWillUnmount() { 
   let xhr = this.state.xhr; 
   // Yêu cầu hủy bỏ XHR, vì thế lệnh callback không được gọi 
   if (xhr && xhr.readyState != 4) { 
   xhr.abort(); 
   } 
 }
componentDidMount() { 
   this.fetchUser(); 
   } 
   fetchUser() { 
   let xhr = $.get('/api/users/self') 
   .then((user) => { 
   this.setState({user: user}); 
   }); 
   this.setState({xhr: xhr}); 
   } 
} 

Phương thức không đồng bộ được lưu dưới dạng các state. Trong componentWillUnmount, bạn thực hiện tất cả quá trình dọn dẹp của mình – bao gồm cả việc hủy yêu cầu XHR.

Bạn có thể làm điều gì đó phức tạp hơn, ví dụ: tạo ra 1 ‘stateSetter’ function rồi chấp nhận đối tượng này làm đối số và ngăn chặn this.setState, khi function được gọi lại

function stateSetter(context) { 
 var cancelled = false; 
 return { 
 cancel: function () { 
 cancelled = true; 
 }, 
 setState(newState) { 
 if (!cancelled) { 
 context.setState(newState); 
 } 
 } 
 } 
} 
class Component extends React.Component { 
 constructor(props) { 
 super(props); 
 this.setter = stateSetter(this); 
 this.state = { 
 user: 'loading' 
 }; 
 } 
 componentWillUnmount() { 
 this.setter.cancel(); 
 } 
 componentDidMount() { 
 this.fetchUser(); 
 } 
 fetchUser() { 
 $.get('/api/users/self') 
 .then((user) => { 
 this.setter.setState({user: user}); 
 }); 
 } 
 render() { 
 return <h1>{this.state.user}</h1> 
 } 
} 

Điều này hoạt động vì biến hủy nằm trong setState mà chúng ta đã tạo

Loại component nào để chọn?

Vâng, nó hoàn toàn phụ thuộc vào yêu cầu cấu trúc của bạn, nhưng có những ưu điểm.

Sử dụng một component lớp nếu bạn muốn sử dụng trạng thái cục bộ, các móc vòng đời khác nhau, nhiều trình xử lý sự kiện hoặc các giá trị trạng thái động dựa trên hoạt động của người dùng.

Sử dụng một component chức năng khi bạn không cần viết logic nghiệp vụ và chỉ cần hiển thị các phần tử giao diện người dùng cụ thể dựa trên giá trị đạo cụ,. Sử dụng hook, bạn cũng có thể sử dụng state vào component hàm.

Phần kết luận

Trong hướng dẫn này, bạn đã học được component là gì và cách tạo component bằng cách sử dụng phương pháp tiếp cận dựa trên lớp và phương pháp dựa trên hàm.

Bạn có thể chọn một trong hai tùy chọn đó để tạo một component dựa trên các yêu cầu kinh doanh của ứng dụng ReactJs của bạn.

Leave a Reply