Class
src\Father.jsx
Copy import { useCallback , useEffect , useMemo , useState , Component , useRef , createRef } from "react" ;
import Child from "./Child" ;
class Father extends Component {
constructor (props) {
super (props);
this .childRef = createRef ();
}
showTextInChild = () => {
console .log ( 'Text in Child :' + this . childRef . current .returnText ())
}
increaseNumberInChild = () => {
this . childRef . current .increaseNumber ()
}
render () {
return (
< div className = "App" >
< Child ref = { this .childRef} />
< button onClick = { this .showTextInChild}>< b style = {{ color : 'red' , background : '#0000' , padding : '5px' }}>Button in Parent</ b > Show Text in Child compoent</ button >
< p ></ p >
< button onClick = { this .increaseNumberInChild}>< b style = {{ color : 'red' , background : '#0000' , padding : '5px' }}>Button in Parent</ b > Increase number in Child compoent</ button >
</ div >
);
}
}
export default Father;
src\Child.jsx
Copy import { useCallback , useEffect , useMemo , useState , Component , useRef , createRef } from "react" ;
class Child extends Component {
constructor (props) {
super (props);
this .state = {
text : "" ,
number : 1 ,
};
}
handleChange = (event) => {
this .setState ({ text : event . target .value });
};
increaseNumber = () => this .setState ({ number : this . state .number + 1 });
returnText = () => this . state .text
render () {
return (
< div >
< input type = "text" onChange = { this .handleChange} />
< p >{ this . state .number}</ p >
</ div >
);
}
}
export default Child;
Function
Copy Chú ý phải sử dụng thêm useImperativeHandle ở Child thì bên Parent mới sử đụng được 😁
src\Father.jsx
Copy import { useCallback , useEffect , useMemo , useState , Component , useRef , createRef } from "react" ;
import Child from "./Child" ;
class Father extends Component {
constructor (props) {
super (props);
this .childRef = createRef ();
}
showTextInChild = () => {
const txt = this . childRef . current .returnText ();
console .log (txt);
};
increaseNumberInChild = () => {
this . childRef . current .incrseaseNumber ();
};
render () {
return (
< div className = "App" >
< Child ref = { this .childRef} />
< button onClick = { this .showTextInChild}>
< b style = {{ color : 'red' , background : '#0000' , padding : '5px' }}>Button in Parent</ b > Show Text in Child compoent
</ button >
< p ></ p >
< button onClick = { this .increaseNumberInChild}>
< b style = {{ color : 'red' , background : '#0000' , padding : '5px' }}>Button in Parent</ b > Increase number in Child compoent
</ button >
</ div >
);
}
}
export default Father;
src\Child.jsx
Copy import { useCallback , useEffect , useMemo , useState , Component , useRef , forwardRef , useImperativeHandle } from "react" ;
const Child = (props , ref) => {
const [ text , setText ] = useState ( "" );
const [ number , setNumber ] = useState ( 1 );
const handleChange = (event) => {
setText ( event . target .value);
};
useImperativeHandle (ref , () => ({
incrseaseNumber : () => setNumber (number + 1 ) ,
returnText : () => text ,
}));
return (
< div >
< input type = "text" onChange = {handleChange} />
< p >{number}</ p >
</ div >
);
};
export default forwardRef (Child);
Hình 2 như chúng ta thấy làm gì có button nào mà sử dụng như trước kia để click vào rồi truyền gía trị nhập từ input ở hình 2 sang hình 1. Nhưng với createRef sử dụng cho Class, useRef sử dụng cho Function (đọc bài viết
) chúng ta hoàn toàn có thể sử dụng chúng một cách dễ dàng.
Đối với các class component chúng sẽ mặc định có thuộc tính ref như mình trình bày với component Child ở trên . Tuy nhiên nếu các component Child là function component , bạn sẽ phải sử dụng thêm forwardRef để bọc Child component như 1 HOC (higher order component) để có thể sử dụng biến ref được truyền vào component Con thông qua props và sử dụng React.useImperativeHandle như sau đây để có thể gọi được các method thông qua thuộc tính ref của được gán giá trị từ component Cha .