I am trying to intergrate forwardRef into a tutoiral prorgam I am following on the basics of useImperativeHandle
import React, {useRef, forwardRef, useState, useImperativeHandle} from "react";
const Button = forwardRef((props,ref)) => {
// ForwardRef allows the child component to recieve a ref.
const [toggle, setToggle] = useState(false);
// Accepts the ref and returns a object of ref values and functions
useImperativeHandle(ref, () => ({
parentAlterToggle() {
setToggle(!toggle);
}
}))
return (
<>
<button
onClick={() => {
setToggle(!toggle);
}}
>
Button From Child
</button>
{toggle && <span>Child Toggled True</span>}
</>
);
}
export default function ImperativeHandle() {
// Lets imaagine that you want to access setToggle in the child button.
// You would think "Lets put that state on the parent button and pass the toggle as a prop"
// However, if you can't do that useImperativeHandle.
const ref = useRef(null)
// Normally, you can't just ref a normal fucntional component. However, add forwardRef to the
// child component, and you can create a ref
return (
<div>
<button onClick={() => {buttonRef.current.parentAlterToggle()}}>Button From Parents</button>
<Button ref={ref} />
</div>
);
}
The closing parentheses you have after the parameter list to the forwardRef wrapped function should be at the end of the function.
const Button = forwardRef((props,ref)) ← this parentheses should be at the end after the closing } of the wrapped function.
In the parent component ImperativeHandle the ref you create should be buttonRef which is also what you should be passing to the ref prop.
Kind of hard to explain without showing it.
Code
import React, {
useRef,
forwardRef,
useState,
useImperativeHandle
} from "react";
const Button = forwardRef((props, ref) => {
// ForwardRef allows the child component to recieve a ref.
const [toggle, setToggle] = useState(false);
// Accepts the ref and returns a object of ref values and functions
useImperativeHandle(ref, () => ({
parentAlterToggle() {
setToggle(!toggle);
}
}));
return (
<>
<button
onClick={() => {
setToggle(!toggle);
}}
>
Button From Child
</button>
{toggle && <span>Child Toggled True</span>}
</>
);
});
export default function ImperativeHandle() {
// Lets imaagine that you want to access setToggle in the child button.
// You would think "Lets put that state on the parent button and pass the toggle as a prop"
// However, if you can't do that useImperativeHandle.
const buttonRef = useRef(null);
// Normally, you can't just ref a normal fucntional component. However, add forwardRef to the
// child component, and you can create a ref
return (
<div>
<button
onClick={() => {
buttonRef.current.parentAlterToggle();
}}
>
Button From Parents
</button>
<Button ref={buttonRef} />
</div>
);
}
As an aside, this is definitely (IMHO) not one of the bright points of React. Other frameworks have much cleaner ways of calling child functions from a parent component (like a dispatch/emit).