forwardRef/createRef
フックセクションのuseRef
をチェックしてください。
createRef
:
import { createRef, PureComponent } from "react";
class CssThemeProvider extends PureComponent<Props> {
private rootRef = createRef<HTMLDivElement>(); // like this
render() {
return <div ref={this.rootRef}>{this.props.children}</div>;
}
}
forwardRef
:
import { forwardRef, ReactNode } from "react";
interface Props {
children?: ReactNode;
type: "submit" | "button";
}
export type Ref = HTMLButtonElement;
export const FancyButton = forwardRef<Ref, Props>((props, ref) => (
<button ref={ref} className="MyClassName" type={props.type}>
{props.children}
</button>
));
補足: forwardRef
から取得したref
は可変なので、必要に応じて割り当てることができます。
意図的にこのようにしました。必要に応じてimmutableにすることができます。誰も再割り当てできないようにしたい場合はReact.Ref
を割り当ててください
import { forwardRef, ReactNode, Ref } from "react";
interface Props {
children?: ReactNode;
type: "submit" | "button";
}
export const FancyButton = forwardRef(
(
props: Props,
ref: Ref<HTMLButtonElement> // <-- here!
) => (
<button ref={ref} className="MyClassName" type={props.type}>
{props.children}
</button>
)
);
参照をフォワードするコンポーネントのプロパティを取得する場合は、ComponentPropsWithRef
を使用してください。
汎用forwardRefs
https://fettblog.eu/typescript-react-generic-forward-refs/で詳細なコンテキストを参照してください。
オプション1 - ラッパコンポーネント
type ClickableListProps<T> = {
items: T[];
onSelect: (item: T) => void;
mRef?: React.Ref<HTMLUListElement> | null;
};
export function ClickableList<T>(props: ClickableListProps<T>) {
return (
<ul ref={props.mRef}>
{props.items.map((item, i) => (
<li key={i}>
<button onClick={(el) => props.onSelect(item)}>Select</button>
{item}
</li>
))}
</ul>
);
}
オプション2 - forwardRefの再宣言
// Redeclare forwardRef
declare module "react" {
function forwardRef<T, P = {}>(
render: (props: P, ref: React.Ref<T>) => React.ReactElement | null
): (props: P & React.RefAttributes<T>) => React.ReactElement | null;
}
// Just write your components like you're used to!
import { forwardRef, ForwardedRef } from "react";
interface ClickableListProps<T> {
items: T[];
onSelect: (item: T) => void;
}
function ClickableListInner<T>(
props: ClickableListProps<T>,
ref: ForwardedRef<HTMLUListElement>
) {
return (
<ul ref={ref}>
{props.items.map((item, i) => (
<li key={i}>
<button onClick={(el) => props.onSelect(item)}>Select</button>
{item}
</li>
))}
</ul>
);
}
export const ClickableList = forwardRef(ClickableListInner);
オプション3 - コールシグネチャ
// Add to `index.d.ts`
interface ForwardRefWithGenerics extends React.FC<WithForwardRefProps<Option>> {
<T extends Option>(props: WithForwardRefProps<T>): ReturnType<
React.FC<WithForwardRefProps<T>>
>;
}
export const ClickableListWithForwardRef: ForwardRefWithGenerics =
forwardRef(ClickableList);
出典: https://stackoverflow.com/a/73795494
詳細情報
forwardRef
を使用して条件レンダリングを実行したい場合があります。