When should I use the hook useImperativeHandle
?
I mean, I think there are multiple ways to use it, and that it is useful to access child state or child methods from a parent component...
So... imagine this situation:
I have a screen "Profile", which implements a pull-to-refresh to update the user data and posts. Posts are rendered in a child component "UserPosts", where I fetch the respective posts of a user (pagination, listeners, ...).
If the Profile screen is the one responsible of fetching the user data and render the <RefreshControl />
, should I pass a ref to my child in order to do userPostsRef.current.fetchNewPosts()
from the parent?
Something like:
- Parent Component
function Profile({ userId }) {
const { userData, fetchUserData } = useFetchUserData(userId);
const [isRefreshing, setIsRefreshing] = useState(false);
const userPostsRef = useRef(null);
const handleOnRefresh = async () => { // simplified, no mutex, no error catching
setIsRefreshing(true);
const promises = [
fetchUserData(),
userPostsRef.current.fetchNewPosts()
];
await Promise.all(promises);
setIsRefreshing(false);
}
...
const renderFooter = () => <UserPosts ref={userPostsRef} userId={userId} />
return (
<FlatList
refreshing={isRefreshing}
onRefresh={handleOnRefresh}
ListHeaderComponent={renderHeader()}
ListFooterComponent={renderFooter()}
/>
);
}
- Child Component (A reusable component that can be placed in different screens, as it is responsible for its own logic...)
const UserPosts = forwardRef({ userId }, ref) => {
const { posts, isLoading, fetchNewPosts, fetchMoreOldPosts } = useFetchUserPosts(userId);
useImperativeHandle(ref, {
fetchNewPosts,
});
return <CardList data={posts} isLoading={isLoading} ... />;
}