Can my React functional component expose externally a method with access to internal state?
interface Inner {
foo: string
}
function Inner(props: Inner) {
const [foo, setFoo] = useState<string>(props.foo + "baz")
function doTheThing() {
console.log(`doin' that ${foo} thing`)
}
return <div>{props.foo}</div>
}
function Outer() {
const inner = <Inner foo="bar" />
return (
<>
<button onClick={() => inner.doTheThing()}>
Do That Thing
</button>
{inner}
</>
)
}
This of course gives me an error: TypeError: inner.doTheThing is not a function.
I can use a class component to expose a method like this. But is there a way (with hooks? with refs?) to make this work with a functional component?
You can pass a ref, and then store doTheThing reference there.
import { MutableRefObject, useRef, useState } from "react";
interface Inner {
foo: string;
dRef: MutableRefObject<{ doTheThing: () => void } | undefined>;
}
function Inner(props: Inner) {
const [foo, setFoo] = useState<string>(props.foo + "baz");
function doTheThing() {
console.log(`doin' that ${foo} thing`);
}
props.dRef.current = { doTheThing };
return <div>{props.foo}</div>;
}
export function Outer() {
const dRef = useRef<{ doTheThing: () => void }>();
const inner = <Inner foo="bar" dRef={dRef} />;
return (
<>
<button onClick={() => dRef.current?.doTheThing()}>Do That Thing</button>
{inner}
</>
);
}