- Bài 1: ReactJS - Lời mở đầu
- Bài 2: ReactJS - Thiết lập môi trường
- Bài 3: ReactJS - JSX
- Bài 4: ReactJS - Components & State
- Bài 5: Props - Tổng quan
- Bài 6: Props - Validation
- Bài 7: ReactJJS - Component API
- Bài 8: ReactJS - Vòng đời của Component
- Bài 9: ReactJS - Forms
- Bài 10: ReactJS - Xử lý sự kiện
- Bài 11: ReactJS - Refs
- Bài 12: ReactJS - List và Keys
- Bài 13: ReactJS - Router
- Bài 14: ReactJS - Khái niệm Flux
- Bài 15: ReactJS - Cách sử dụng Flux
- Bài 16: ReactJS - Animation
- Bài 17: ReactJS - Higher Order Components
- Bài 18: ReactJS - Bản rút gọn(Quick guide - P1)
- Bài 19: ReactJS - Bản rút gọn(Quick guide - P2)
- Bài 20: ReactJS - Bản rút gọn(Quick guide - P3)
- Bài 21: ReactJS - Tạo ứng dụng reatjs từ bootstrap 4
Bài 11: ReactJS - Refs - Học ReactJS Full Đầy Đủ Nhất
Đăng bởi: Admin | Lượt xem: 4361 | Chuyên mục: Javascript
1. Giới thiệu về Refs
Trong data flow của React, props là cách để các parent components tương tác với các child components. Để updated child componnent, bạn cần re-render nó với các props mới. Nhưng sẽ có một số trường hợp cần bắt buộc phải updated các child component bên ngoài data flow của React. Các child component có thể là 1 instance của React Component hoặc có thể là DOM element. Cho những trường hợp này, chúng ta có thể sử dụng react Refs.
Đối với các bạn mới tiếp xúc với React , chắc hẳn có những khái niệm, cú pháp khá khó hiểu và phức tạp, ko dễ để tiếp cận, trong đó có "refs" . Qua bài này mình xin giới thiệu lại và tìm hiểu sâu về refs trong react. Theo tài liệu của React, refs được sử dụng để lấy tham chiếu đến một node DOM(Document Object Model) hoặc có thể là một thể hiện của một component trong một ứng dụng React. tức là refs sẽ return về một node mà chúng ta tham chiếu đến. Nào cùng xem một vài ví dụ
App.jsx
export default class index extends React.Component {
constructor() {
super();
this.state = {sayings: "" };
}
update(e) {
this.setState({sayings: e.target.value});
}
render() {
return (
<div>
Bob says <input type="text" onChange={this.update.bind(this)} />
{this.state.sayings}
</div>
);
}
}
Trong ví dụ trên, việc nhận được giá trị Bob nói chúng ta dùng giá trị target của sự kiện thay đổi trong thẻ input. Sử dụng refs có thể thực hiện theo cách sau.
export default class index extends React.Component {
constructor() {
super();
this.state = {sayings: "" };
}
update(e) {
this.setState({sayings: this.refs.btalks.value});
}
render() {
return (
<div>
Bob says <input type="text" ref="btalks" onChange={this.update.bind(this)} />
{this.state.sayings}
</div>
);
}
}
Ngoài ra chúng ta có thể bỏ qua một callback trong refs bằng cách đặt tên cho node đó .
update(e) {
this.setState({sayings: this.a.value});
}
render() {
return (
<div>
Bob says <input type="text" ref={(node) => {this.a = node}} onChange={this.update.bind(this)} />
Khi bạn cần refs thay vì ID's Như đã biết thì ID's hoạt động như một phần tử độc lập trong toàn bộ cây DOM , có ví dụ sau
export default class index extends React.Component {
constructor() {
super();
this.state = {sayings: "" };
}
onFocus() {
document.getElementById('myInput').style.backgroundColor='red';
}
render() {
return (
<div>
Bob angry <input type="button" id="myInput" onFocus={this.onFocus.bind(this)} />
<br/>
Tim angry <input type="button" id="myInput" onFocus={this.onFocus.bind(this)} />
</div>
);
}
}
Ô của bob sẽ luôn được tô đỏ so với của Tim vì cả 2 đều cùng Id. Nếu chúng ta sử dụng refs chúng ta có thể thay thế IDs với một tên refs cụ thể là được. Khi cần trả về một node DOM hoặc một component Nếu các ref points đến môt component tiêu chuẩn (node DOM, input, select, div..) sau đó để lấy các phần tử, chỉ cần gọi this.refs.ref. Nếu các ref points đến một tổ hợp các component bạn cần sử dụng ReactDOM module : ReactDOM.findDOMNode(this.refs.ref.)
Khi nào thì giá trị đầu tiền của ref được set? Trong các render(), lifecycle methods tồn tại gồm có: ComponentWillMount(), ComponentDidMount(), ComponentWillUnmount(),.. ref đầu tiên sẽ được set đầu tiên ở render nhưng trước ComponentDidMount(), Khi nào nên sử dụng refs
2. Một số trường hợp dùng refs
- Control focus; get text của DOM element; get state value(play/pause/timeline) của media playback,... nói chung là dùng trong những trường hợp các data này không cần đưa vào state của component.
- Trigger các transitions, animations: sử dụng refs khi một element cần trigger animation/transition của một element khác
- Tích hợp với các Third-party DOM libraries
Chú ý khi sử dụng refs
a - Don’t Inline refs callbacks(không gọi phươg thức refs trong cùng 1 dòng code):
Bob says <input type="text" ref={(node) => {this.a = node}} onChange={this.update.bind(this)} />
=> và function bind trong 1 render() sẽ sản sinh ra một performance bởi mỗi lần
=> và function bind trong 1 render() sẽ sản sinh ra một performance bởi mỗi lần hàm đó render mới lại. Vậy nên hãy dùng
Bob says <input type="text" ref={this.setRef} onChange={this.update.bind(this)} />
Ngoài ra nếu ref call back sẽ được định nghĩa như function nội tuyến, nó sẽ bị gọi lại 2 lần trong quá trình cập nhật, lần đầu sẽ trả về null và tiếp theo mới trả về phần tử DOM. React sẽ thực hiện viện dọn dẹp các ref cũ và set up ref mới chỉ trong trường hợp những bước phía trước vào callback tiếp theo thực hiện những chức năng khác nhau.
b - Đặt tên refs là chuỗi cũng là không nên
Bob says <input type="text" ref="btalks" onChange={this.update.bind(this)} />
c - ref không nên dùng trên các component không có chức năng là thẻ DOM , ví dụ ref dùng trên component trả về 1 input:
Nhưng thuộc tính ref sẽ làm việc trong component miễn là bạn đề cập đến một phần tử DOM hoặc một class component:
3. Sử dụng useRef của react hooks
Cú pháp :
const refContainer = useRef(initialValue);
Đoạn code ở trên, chúng ta sẽ khởi tạo 1 ref object có .current property với initialValue. useRef sẽ cho cùng 1 ref object trên mỗi lần render.
- Nếu ref object này là 1 DOM element thì chúng ta có thể manipulated các DOM element này như pure javascript thường làm.
- Nếu ref object này là 1 javascript object thì các object này sẽ tồn tại trong scope của component như 1 plain javascript object thông thường.
4. Các ví dụ:
Ví dụ 1 : Điều khiển focus của input:
Ở ví dụ này, chúng ta sẽ sử dụng userRef để tham chiếu tới input element, sau đó sẽ thực hiện focus input khi click button
import React, { useRef } from "react";
function App() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<div className="App">
<h2>Use refs to control focus</h2>
<input ref={inputEl} />
<button onClick={onButtonClick}>Focus the input</button>
</div>
);
}
Set/Get giá trị trước đó của state:
Ở ví dụ này; sẽ có 1 input, nhập một vài ký tự và thực hiện blur input đó, chúng ta sẽ check xem previous value, current value sau mỗi lần blur input (case này trong thực tế là: nếu sau mỗi lần blur mà giá trị trước và sau khi blur có thay đổi thì thực hiện call api, ngược lại nếu không thay đổi thì không làm gì cả)
import React, { useRef, useState } from "react";
function App() {
const prevValue = useRef("");
const [value, setValue] = useState("");
const onInputChange = e => {
setValue(e.target.value);
};
const onInputBlur = () => {
console.log(`Previous value: ${prevValue.current}`);
console.log(`Current value: ${value}`);
prevValue.current = value;
};
return (
<div className="App">
<h2>Use refs to set/get previous state's value</h2>
<input value={value} onBlur={onInputBlur} onChange={onInputChange} />
<div>Type something, blur input and check result in console.log</div>
</div>
);
}
Sau khi hiểu về useRef ở ví dụ trên, chúng ta sẽ hay gặp 1 trường hợp thực tế như sau: sau khi input data vào các field trên màn hình(route A) sau đó điều hướng sang route B, lúc này ta sẽ cần lưu các data trên màn hình vào redux store như sau:
import React, { useState, useEffect, useRef } from "react";
function App() {
const onScreenData = useRef({});
const [inputs, setInputs] = useState({});
const onInputChange = e => {
const [name, value] = e.target;
const updatedInputs = { ...inputs, [name]: value };
setInputs(updatedInputs);
onScreenData.current = updatedInputs;
};
useEffect(
() => () => {
saveScreenData(onScreenData.current);
},
[]
);
return (
<div>
<h2>Use refs to get the latest inputs value</h2>
<label>Title: </label>
<input name="title" value={inputs.title || ""} onChange={onInputChange} />
<label>Note: </label>
<input name="note" value={inputs.note || ""} onChange={onInputChange} />
</div>
);
}
const saveScreenData = data => {
// Save data to redux store
};
Control animation:
Chúng ta sử dụng useRef để get tham chiếu đến DOM element và thực hiện trigger animation
import React, { useRef, useEffect } from "react";
import { TweenMax } from "gsap";
function App() {
const circle = useRef(null);
useEffect(() => {
TweenMax.fromTo(
[circle.current],
0.5,
{ y: 18 },
{ y: -18, yoyo: true, repeat: -1 }
);
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<svg viewBox="0 0 150 33.2" width="180" height="150">
<circle ref={circle} cx="16.1" cy="16.6" r="16.1" fill="#527abd" />
</svg>
</div>
);
}
Ví dụ 2 :
Ví dụ này hướng dẫn bạn cách sử dụng refs để xoá box input. Hàm ClearInput sẽ tìm phần tử với ref = giá trị "myInput"
App.jsx
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: ''
}
this.updateState = this.updateState.bind(this);
this.clearInput = this.clearInput.bind(this);
};
updateState(e) {
this.setState({data: e.target.value});
}
clearInput() {
this.setState({data: ''});
ReactDOM.findDOMNode(this.refs.myInput).focus();
}
render() {
return (
<div>
<input value = {this.state.data} onChange = {this.updateState}
ref = "myInput"></input>
<button onClick = {this.clearInput}>CLEAR</button>
<h4>{this.state.data}</h4>
</div>
);
}
}
export default App;
main.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App/>, document.getElementById('app'));
Cứ sau một lần bạn nhấn vào nút CLEAR thì input sẽ bị xoá đi
5. Kết luận :
Ở trên là một số ví dụ về sử dụng refs trong react hook, nhưng chúng ra hãy lưu ý một điều là nên hạn chế sử dụng refs mà thay vào đó là sử dụng state để control React Component; còn những trường hợp mà không thể dùng state, props thì mới sử dụng refs; trong đó những trường hợp thao tác với DOM element là hay sử dụng refs nhất.
Cám ơn các bạn đã đọc bài viết, hy vọng cá
Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!
- Bài 1: ReactJS - Lời mở đầu
- Bài 2: ReactJS - Thiết lập môi trường
- Bài 3: ReactJS - JSX
- Bài 4: ReactJS - Components & State
- Bài 5: Props - Tổng quan
- Bài 6: Props - Validation
- Bài 7: ReactJJS - Component API
- Bài 8: ReactJS - Vòng đời của Component
- Bài 9: ReactJS - Forms
- Bài 10: ReactJS - Xử lý sự kiện
- Bài 11: ReactJS - Refs
- Bài 12: ReactJS - List và Keys
- Bài 13: ReactJS - Router
- Bài 14: ReactJS - Khái niệm Flux
- Bài 15: ReactJS - Cách sử dụng Flux
- Bài 16: ReactJS - Animation
- Bài 17: ReactJS - Higher Order Components
- Bài 18: ReactJS - Bản rút gọn(Quick guide - P1)
- Bài 19: ReactJS - Bản rút gọn(Quick guide - P2)
- Bài 20: ReactJS - Bản rút gọn(Quick guide - P3)
- Bài 21: ReactJS - Tạo ứng dụng reatjs từ bootstrap 4