Reading time is about 6 minutes.
We improved the flexibility of React components in " yesterday. Learn more about React's & nbsp in the article "learn more about the wonderful use of forwardRef API " forwardRef
& nbsp;API. When we need to manipulate a DOM node in a subcomponent, forwardRef
& nbsp; meets our needs very well. But what if we want to manipulate some methods or properties in the subcomponent?
you may immediately think of using a callback function to expose the methods or properties that need to be exposed in the child component to the parent component. For example, the following code:
import React from 'react';
// Sub-component
function ChildComponent(props) {
const otherOperate = () => {
// some code...
}
const handleClick = () => {
if (props.onClick) {
// callback function passed by the parent component
props.onClick({ otherOperate });
}
};
return (
<button onClick={handleClick}>
Click me!
</button>
);
}
// parent component
function ParentComponent() {
const handleClick = (propsFromChild) => {
console.log('Button clicked!', propsFromChild);
};
return (
<div>
<ChildComponent onClick={handleClick} />
</div>
);
}
export default ParentComponent;
in the above example, we pass the & nbsp; handleClick
& nbsp; function as the & nbsp; onClick
& nbsp; attribute to the & nbsp; ChildComponent
& nbsp; subcomponent. When the button in & nbsp; ChildComponent
& nbsp; is clicked, the handleClick
& nbsp; function is called, exposing the & nbsp; otherOperate
& nbsp; method in the child component to the parent component. In this way, when we click the button of the child component, the parent component can access the methods exposed by the child component, thus realizing the communication between the parent and child components.
Communication between parent and child components is carried out by callback function, and the parent component can only call the methods exposed by the child component, but cannot directly access the internal state and properties of the child component. (the ability to skillfully use the callback function is very important. At the end of the article, I have prepared a large ebook on JS for you for free. Remember to pick it up later)
is there a way to access the internal state and properties of child components in the parent component?
next, let's take a look at one of the very powerful hook functions in React.
first acquaintance & nbsp; useImperativeHandle
useImperativeHandle
& nbsp; is a hook function in React that exposes a component's ref so that the parent component can call some methods and properties of the child component.
useImperativeHandle
& nbsp; hook function has a very wide range of uses, flexible use of this hook function can bring great convenience for our development. For example, if we encapsulate a player in a child component, the parent component may need to control the playback, pause, stop and other operations of the player, and then we can use & nbsp; useImperativeHandle
& nbsp; to expose these operations to the parent component.
for example, in the example above, the & nbsp; otherOperate
& nbsp; in the subcomponent is exposed through the callback function, we can use & nbsp; useImperativeHandle
& nbsp; to achieve this, and the parent component can also directly access the internal state and properties of the subcomponent.
introduces so much, how should I use & nbsp; useImperativeHandle
& nbsp;?
useImperativeHandle
& basic usage of nbsp;
useImperativeHandle(ref, createHandle, [deps]);
useImperativeHandle
& nbsp; accepts three parameters:
-
ref
: a Ref object, generally speaking, is passed from the parent component. -
createHandle
: a callback function that returns an object whose properties and methods are exposed to the parent component. -
[deps]
: optional parameter, an array that specifies the dependencies of the callback function. When these dependencies change, the callback function is reexecuted. If you do not specify a dependency, the callback function is executed only once when the component is first rendered.
when using the & nbsp; useImperativeHandle
& nbsp; hook function in the child component, we need to pass the ref from the parent component and return an object in the callback function. The properties and methods in this object are exposed to the parent component for use. It is important to note that only the object properties and methods returned in the callback function are exposed, while other properties and methods in the subcomponent are not.
when using & nbsp; useImperativeHandle
& nbsp;, we can also specify the dependency of the callback function through the & nbsp; [deps]
& nbsp; parameter to avoid unnecessary repeated rendering. When these dependencies change, the callback function is reexecuted. If you do not specify a dependency, the callback function is executed only once when the component is first rendered.
Let's demonstrate how to use & nbsp; useImperativeHandle
with an example of a counter.
counter example
first, let's write the counter component with the following code:
import React, { forwardRef, useImperativeHandle, useState } from 'react';
// use the forwardRef function to create a Counter component and pass in the ref parameter
const Counter = forwardRef((props, ref) => {
// use useState to create a state called count with an initial value of 0
const [count, setCount] = useState(0);
// create an increase function to increase the value of the counter
const increase = () => {
setCount(count + 1);
};
// create a function decrease to reduce the value of the counter
const decrease = () => {
setCount(count - 1);
};
// using useImperativeHandle hook, expose the ref to the parent component and return an object to the
// the increase and decrease methods are included in the image, so that the parent component can call these two methods directly
// to modify the value of the counter
useImperativeHandle(ref, () => ({
increase,
decrease,
}));
// returns a div element containing the current counter value
return <div>{count}</div>;
});
// Export Counter components
export default Counter;
in the above code, we use & nbsp; useImperativeHandle
& nbsp; to expose & nbsp; increase
& nbsp; and & nbsp; decrease
& nbsp;, so that the parent component can directly call these two methods to modify the value of the counter. Note that the object properties and methods returned in the callback function are exposed, while other properties and methods are not. Here, we only expose & nbsp; increase
& nbsp; and & nbsp; decrease
& nbsp;, while & nbsp; count
& nbsp; state is not exposed.
next, reference the counter component, nbsp; Counter
, in the parent component and demonstrate how to call the methods it exposes to manipulate the value of the counter. The code is as follows:
import React, { useRef } from 'react';
import Counter from './Counter';
const App = () => {
// use useRef hook to create a reference named counterRef
const counterRef = useRef();
// create a function named handleIncrease to increase the value of the counter
const handleIncrease = () => {
// get the Counter component instance through counterRef.current and call the increase method exposed by it
counterRef.current.increase();
};
// create a function called handleDecrease to reduce the value of the counter
const handleDecrease = () => {
// get the Counter component instance through counterRef.current and call the decrease method exposed by it
counterRef.current.decrease();
};
// returns a div element that contains a Counter component and two buttons
// clicking the button will trigger the handleIncrease and handleDecrease functions exposed by the subcomponents, thus manipulating the value of the counter
return (
<div>
<Counter ref={counterRef} />
<button onClick={handleIncrease}>Increase</button>
<button onClick={handleDecrease}>Decrease</button>
</div>
);
};
export default App;
in the code above, we use & nbsp; useRef
& nbsp; to create a Ref object & nbsp; counterRef
and pass it to the & nbsp; Counter
& nbsp; component. Next, we define two functions & nbsp; handleIncrease
& nbsp; and & nbsp; handleDecrease
& nbsp;. Inside the function, the & nbsp; increase
& nbsp; and & nbsp; decrease
& nbsp; methods exposed by & nbsp; counterRef.current
& nbsp; are respectively called. In this way, we can increase or decrease the value of the child component counter through these two buttons in the parent component.
well, is this method more flexible than using callback functions? In fact, using callback functions has many disadvantages, if a subcomponent receives many callback functions, it will be very difficult for us to maintain. Using the & nbsp; useImperativeHandle
& nbsp; hook function avoids passing multiple callback functions to the child component. Furthermore, callback functions can access certain methods or properties exposed by subcomponents only after certain events have been triggered, while & nbsp; useImperativeHandle
& nbsp; allows us to access methods and properties in subcomponents at any time. So, in general, if you encounter a scenario where you need to access methods and properties in a child component in the parent component, go directly to & nbsp; useImperativeHandle
& nbsp;.
Summary
all the people who have slipped here are true love 😘. Have you found yourself get to a new skill ^ _ ^
after watching it?
Yes, to make better use of & nbsp; useImperativeHandle
& nbsp; is inseparable from the flexible use of & nbsp; forwardRef
& nbsp; and & nbsp; useRef
& nbsp;.
mastery of & nbsp; useImperativeHandle
& the nbsp; hook function allows us to easily expose methods and properties in the child component, thus giving the parent component more flexibility to manipulate the child component. In actual projects, people can expose different methods and properties according to their needs to achieve more flexible and efficient component design.
if you think it is helpful to you, you can also share it with your good friends and colleagues to learn and make progress.
of course, if you find any mistakes in the article, you are welcome to leave a comment below and 🫡
Comments