Tự học React JS trọn bộ kiến thức cơ bản – phần 2

Tiếp theo phần 1, ở phần này, chúng ta sẽ tìm hiểu rõ hơn về react. Cùng lướt qua bài viết ngay nào


1065

Component React

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.

Stateless react

Component đầu tiên của chúng ta trong ví dụ sau là App. Chúng ta tạo Header, Content  và chỉ cần thêm nó vào JSX trong component react. Chỉ component App mới cần export

import React from 'react';
class App extends React.Component {
   render() {
      return (
         <div>
            <Header/>
            <Content/>
         </div>
      );
   }
}
class Header extends React.Component {
   render() {
      return (
         <div>
            <h1>Header</h1>
         </div>
      );
   }
}
class Content extends React.Component {
   render() {
      return (
         <div>
            <h2>Content</h2>
            <p>The content text!!!</p>
         </div>
      );
   }
}
export default App;

Để có thể hiển thị điều này trên trang, chúng ta cần import nó vào file main.js và gọi reactDOM.render(). Chúng ta đã làm điều này trong khi setup environment react.

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App />, document.getElementById('app'));

Kết quả sẽ được như sau

React Component Stateless

Stateful react

Trong ví dụ này, chúng ta sẽ set state cho component app. Component Header chỉ được thêm vào như ví dụ trước vì không cần bất kỳ trạng thái nào. Thay vì tag(thẻ) nội dung, chúng ta tạo các phần tử table và tbody, nơi chèn TableRow cho mọi đối tượng từ mảng dữ liệu trong react.

Có thể thấy rằng chúng ta sử dụng cú pháp mũi tên (=>) dễ nhìn hơn nhiều so với cú pháp JavaScript cũ. Điều này sẽ giúp tạo ra với ít dòng code hơn. Đặc biệt hữu ích khi chúng ta cần tạo một danh sách với rất nhiều mục.

import React from 'react';
class App extends React.Component {
   constructor() {
      super();
      this.state = {
         data:
         [
            {
               "id":1,
               "name":"Foo",
               "age":"20"
            },
            {
               "id":2,
               "name":"Bar",
               "age":"30"
            },
            {
               "id":3,
               "name":"Baz",
               "age":"40"
            }
         ]
      }
   }
   render() {
      return (
         <div>
            <Header/>
            <table>
               <tbody>
                  {this.state.data.map((person, i) => <TableRow key = {i}
                     data = {person} />)}
               </tbody>
            </table>
         </div>
      );
   }
}
class Header extends React.Component {
   render() {
      return (
         <div>
            <h1>Header</h1>
         </div>
      );
   }
}
class TableRow extends React.Component {
   render() {
      return (
         <tr>
            <td>{this.props.data.id}</td>
            <td>{this.props.data.name}</td>
            <td>{this.props.data.age}</td>
         </tr>
      );
   }
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App/>, document.getElementById('app'));

Lưu ý – Chúng ta đang sử dụng hàm key = {i} bên trong hàm map (). Điều này sẽ giúp React chỉ cập nhật các yếu tố cần thiết thay vì hiển thị lại toàn bộ danh sách khi có gì đó thay đổi. Giúp tăng hiệu suất lớn cho số lượng lớn hơn các yếu tố được tạo động.

Kết quả như sau :

React Component Statefull

State

Trong React, state là các thành phần để xây dựng nên một component.

State là lưu lưu trữ các giá trị của component, khi state thay đổi thì component cũng được render lại.

Code sau đây cho thấy cách tạo một component state

import React from 'react';
class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         header: "Header from state...",
         content: "Content from state..."
      }
   }
   render() {
      return (
         <div>
            <h1>{this.state.header}</h1>
            <h2>{this.state.content}</h2>
         </div>
      );
   }
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App />, document.getElementById('app'));

Và đây là kết quả

React State Simple

Tổng quan về Props React

Sự khác biệt chính giữa state và props là props bất biến. Đây là lý do tại sao component container nên xác định state để cập nhật và thay đổi, trong khi các thành phần con chỉ nên truyền dữ liệu từ state bằng cách sử dụng props trên react

Cách sử dụng props

Khi chúng ta cần dữ liệu bất biến trong component, chúng ta chỉ cần thêm props vào hàm reactDom.render() trong tệp main.js.

import React from 'react';
class App extends React.Component {
   render() {
      return (
         <div>
            <h1>{this.props.headerProp}</h1>
            <h2>{this.props.contentProp}</h2>
         </div>
      );
   }
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App headerProp = "Header from props..." contentProp = "Content
   from props..."/>, document.getElementById('app'));
export default App;

Kết quả sẽ như sau:

React Props Example

Props mặc định

Bạn cũng có thể đặt các giá trị thuộc tính mặc định trực tiếp trên hàm tạo component thay vì thêm nó vào phần tử reactDom.render().

import React from 'react';
class App extends React.Component {
   render() {
      return (
         <div>
            <h1>{this.props.headerProp}</h1>
            <h2>{this.props.contentProp}</h2>
         </div>
      );
   }
}
App.defaultProps = {
   headerProp: "Header from props...",
   contentProp:"Content from props..."
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App/>, document.getElementById('app'));
React Props Example

State và Props

Ví dụ sau đây cho thấy cách kết hợp state và props trong ứng dụng của bạn. Chúng ta thiết lập state trong component cha và chuyển nó sử dụng props. Bên trong hàm render(), set headerProp và contentProp được sử dụng trong các thành phần con.

import React from 'react';
class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         header: "Header from props...",
         content: "Content from props..."
      }
   }
   render() {
      return (
         <div>
            <Header headerProp = {this.state.header}/>
            <Content contentProp = {this.state.content}/>
         </div>
      );
   }
}
class Header extends React.Component {
   render() {
      return (
         <div>
            <h1>{this.props.headerProp}</h1>
         </div>
      );
   }
}
class Content extends React.Component {
   render() {
      return (
         <div>
            <h2>{this.props.contentProp}</h2>
         </div>
      );
   }
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App/>, document.getElementById('app'));
React Props Example

Qua 2 ví dụ trên, bạn đã hiểu rõ hơn về state và props. Và cách sử dụng hợp lý

Validating Props

Validating Props là cách để kiểm soát các vấn đề về props, nó cho phép bạn kiểm tra dữ liệu đầu vào của props trước khi components được render. Props validation giúp chúng ta giảm thiểu các lỗi không mong muốn trong quá trình xây dựng ứng dụng React.

Trong ví dụ này, chúng ta tạo component app với tất cả các props mà chúng ta cần. App.propTypes được sử dụng để validating Props. Sau đó chúng ta set App.defaultProps.

import React from 'react';
class App extends React.Component {
   render() {
      return (
         <div>
            <h3>Array: {this.props.propArray}</h3>
            <h3>Bool: {this.props.propBool ? "True..." : "False..."}</h3>
            <h3>Func: {this.props.propFunc(3)}</h3>
            <h3>Number: {this.props.propNumber}</h3>
            <h3>String: {this.props.propString}</h3>
            <h3>Object: {this.props.propObject.objectName1}</h3>
            <h3>Object: {this.props.propObject.objectName2}</h3>
            <h3>Object: {this.props.propObject.objectName3}</h3>
         </div>
      );
   }
}
App.propTypes = {
   propArray: React.PropTypes.array.isRequired,
   propBool: React.PropTypes.bool.isRequired,
   propFunc: React.PropTypes.func,
   propNumber: React.PropTypes.number,
   propString: React.PropTypes.string,
   propObject: React.PropTypes.object
}
App.defaultProps = {
   propArray: [1,2,3,4,5],
   propBool: true,
   propFunc: function(e){return e},
   propNumber: 1,
   propString: "String value...",
   propObject: {
      objectName1:"objectValue1",
      objectName2: "objectValue2",
      objectName3: "objectValue3"
   }
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App/>, document.getElementById('app'));

Và đây là kết quả:

Props are Valid

Component API

Trong phần này, chúng tasẽ giải thích component api React. Chúng ta sẽ thảo luận về ba phương thức: setState(), forceUpdate()ReactDOM.findDOMNode(). Trong các class ES6 mới, chúng ta phải liên kết thủ công này bằng cách sử dụng this.method.bind (this) trong các ví dụ.

setState()

Phương thức setState () được sử dụng để cập nhật trạng thái của component. Phương pháp này sẽ không thay thế state mà chỉ thêm các thay đổi về trạng thái ban đầu.

import React from 'react';
class App extends React.Component {
   constructor() {
      super();
      this.state = {
         data: []
      }
      this.setStateHandler = this.setStateHandler.bind(this);
   };
   setStateHandler() {
      var item = "setState..."
      var myArray = this.state.data.slice();
	  myArray.push(item);
      this.setState({data: myArray})
   };
   render() {
      return (
         <div>
            <button onClick = {this.setStateHandler}>SET STATE</button>
            <h4>State Array: {this.state.data}</h4>
         </div>
      );
   }
}
export default App;

Chúng ta bắt đầu với một mảng trống. Mỗi khi nhấp vào button, state sẽ được cập nhật. Nếu nhấp năm lần, chúng ta sẽ nhận được kết quả sau trên React:

React Component API Set State

forceUpdate()

Đôi khi muốn cập nhật component bằng tay. Điều này có thể làm bằng cách sử dụng phương thức forceUpdate ().

import React from 'react';
class App extends React.Component {
   constructor() {
      super();
      this.forceUpdateHandler = this.forceUpdateHandler.bind(this);
   };
   forceUpdateHandler() {
      this.forceUpdate();
   };
   render() {
      return (
         <div>
            <button onClick = {this.forceUpdateHandler}>FORCE UPDATE</button>
            <h4>Random number: {Math.random()}</h4>
         </div>
      );
   }
}
export default App;

Kết quả sẽ như sau khi click vào button

ReactDOM.findDOMNode()

Để thao tác DOM, chúng ta có thể sử dụng phương thức ReactDOM.findDOMNode (). Đầu tiên chúng ta cần import react-dom.

import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
   constructor() {
      super();
      this.findDomNodeHandler = this.findDomNodeHandler.bind(this);
   };
   findDomNodeHandler() {
      var myDiv = document.getElementById('myDiv');
      ReactDOM.findDOMNode(myDiv).style.color = 'green';
   }
   render() {
      return (
         <div>
            <button onClick = {this.findDomNodeHandler}>FIND DOME NODE</button>
            <div id = "myDiv">NODE</div>
         </div>
      );
   }
}
export default App;

Màu của phần tử myDiv chuyển sang màu xanh, sau khi click vào button.

Vòng đời component trong react

  • componentWillMount được thực thi trước khi render, trên cả máy chủ và client(phía máy khách).
  • componentDidMount được thực hiện sau khi render đầu tiên chỉ ở client. Đây là nơi xảy ra yêu cầu AJAX và DOM hoặc cập nhật trạng thái. Phương thức này cũng được sử dụng để tích hợp với các frameworks  JavaScript khác và bất kỳ chức năng nào bị thực thi bị trì hoãn như setTimeout hoặc setInterval
  • componentWillReceiveProps được gọi ngay sau khi props được cập nhật trước khi một render khác được gọi. Đã kích hoạt nó từ setNewNumber khi cập nhật trạng thái.
  • shouldComponentUpdate nên trả về giá trị true hoặc false. Điều này xác định nếu component được cập nhật hay không. Mặc định là true.
  • componentWillUpdate được gọi trước khi render.
  • componentDidUpdate được gọi sau khi render.
  • componentWillUnmount được gọi sau khi component được ngắt từ dom. Chúng tôi kết nối component trong main.js.

Trong ví dụ sau, chúng ta đặt trạng thái ban đầu trong hàm constructor. SetNewnumber được sử dụng để cập nhật trạng thái. Tất cả các phương thức vòng đời đều nằm trong component Content .

import React from 'react';
class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         data: 0
      }
      this.setNewNumber = this.setNewNumber.bind(this)
   };
   setNewNumber() {
      this.setState({data: this.state.data + 1})
   }
   render() {
      return (
         <div>
            <button onClick = {this.setNewNumber}>INCREMENT</button>
            <Content myNumber = {this.state.data}></Content>
         </div>
      );
   }
}
class Content extends React.Component {
   componentWillMount() {
      console.log('Component WILL MOUNT!')
   }
   componentDidMount() {
      console.log('Component DID MOUNT!')
   }
   componentWillReceiveProps(newProps) {
      console.log('Component WILL RECIEVE PROPS!')
   }
   shouldComponentUpdate(newProps, newState) {
      return true;
   }
   componentWillUpdate(nextProps, nextState) {
      console.log('Component WILL UPDATE!');
   }
   componentDidUpdate(prevProps, prevState) {
      console.log('Component DID UPDATE!')
   }
   componentWillUnmount() {
      console.log('Component WILL UNMOUNT!')
   }
   render() {
      return (
         <div>
            <h3>{this.props.myNumber}</h3>
         </div>
      );
   }
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App/>, document.getElementById('app'));
setTimeout(() => {
   ReactDOM.unmountComponentAtNode(document.getElementById('app'));}, 10000);

Màn hình sẽ hiển thị như vậy khi render lần đầu tiên.

Forms trong React

Về cơ bản, form là một đối tượng html được sử dụng để có thể tương tác với người dùng. Một HTML form bao chứa lấy các phần tử bên trong của nó. Các phần tử html được sử dụng trong form tương đối đa dạng nhưng được sử dụng thông dụng nhất như input, checkbox, radio button, submit button…

Ví dụ đơn giản

Trong ví dụ sau, chúng ta đặt form với value = {this.state.data}. Điều này cho phép cập nhật state bất cứ khi nào giá trị đầu vào thay đổi. Sử dụng sự kiện onChange theo dõi các thay đổi đầu vào và cập nhật state phù hợp.

import React from 'react';
class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         data: 'Initial data...'
      }
      this.updateState = this.updateState.bind(this);
   };
   updateState(e) {
      this.setState({data: e.target.value});
   }
   render() {
      return (
         <div>
            <input type = "text" value = {this.state.data}
               onChange = {this.updateState} />
            <h4>{this.state.data}</h4>
         </div>
      );
   }
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App/>, document.getElementById('app'));

Kết quả sẽ như sau:

Phức tạp

Trong ví dụ sau, chúng ta sẽ xem cách sử dụng các forms từ component con. Phương thức onChange cập nhật state được chuyển đến giá trị đầu vào con và được hiển thị trên màn hình.

Bất cứ khi nào chúng ta cần cập nhật state từ component con, chúng ta cần truyền function xử lý cập nhật (updateState) dưới dạng prop (updateStateProp).

import React from 'react';
class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         data: 'Initial data...'
      }
      this.updateState = this.updateState.bind(this);
   };
   updateState(e) {
      this.setState({data: e.target.value});
   }
   render() {
      return (
         <div>
            <Content myDataProp = {this.state.data}
               updateStateProp = {this.updateState}></Content>
         </div>
      );
   }
}
class Content extends React.Component {
   render() {
      return (
         <div>
            <input type = "text" value = {this.props.myDataProp}
               onChange = {this.props.updateStateProp} />
            <h3>{this.props.myDataProp}</h3>
         </div>
      );
   }
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App/>, document.getElementById('app'));

Kết quả sẽ hiển thị như sau

Kết luận

Qua phần 2 , chúng ta càng hiểu rõ hơn về state, stateless, forms, … để có thể cải thiện hơn app. Tăng tốc độ và tối ưu hóa code của bản thân


Like it? Share with your friends!

1065