編集:この問題は、ForwardRef を Redux 接続と組み合わせて使用しようとしたために発生しました。解決策については、この投稿をご覧ください。
React.forwardRef を使用して、親コンポーネントの DOM 要素にアクセスしようとしています。問題は、最初のレンダリングの後でも ref.current が定義されないことです。
この親コンポーネントでは、子コンポーネントの 1 つから DOM 要素にアクセスしたいと考えています。
const MyFunctionComponent = () => {
const bannerRef = useRef<HTMLDivElement>(null);
let bannerIndent = useRef<string>();
useEffect(() => {
// bannerRef.current is ALWAYS null. Why?
if (bannerRef.current) {
// this conditional block never runs, so bannerIndent is never defined
const bannerWidth = bannerRef.current.getBoundingClientRect().width;
bannerIndent.current = `${bannerWidth}px`;
}
}, []);
return (
<>
<Banner ref={bannerRef} />
<ComponentTwo bannerIndent={bannerIndent.current} />
</>
)
}
転送された参照を受け取るコンポーネント:
const Banner = React.forwardRef<HTMLDivElement, Props> ((props, ref) => (
<div ref={ref} />
));
転送された参照から派生したデータを必要とするコンポーネント:
const ComponentTwo = (props: {bannerIndent?: string}) => (
<StyledDiv bannerIndent={props.bannerIndent} />
)
// styled.div is a styled-component
const StyledDiv = styled.div<{bannerIndent?: string}>`
... // styles, some of which depend on bannerIndent
`
forwardRef が常に null または未定義であることを議論する既存の SO の質問への回答は、ref が最初のレンダリング後にのみ定義されることを指摘しています。useEffect は最初のレンダリングの後に実行する必要がありますが、bannerRef.current はまだ null であるため、これは問題ではないと思います。
通常の ref を使用して Banner コンポーネント内で使用すると、 useEffect フックで bannerIndent の値を設定するロジックが正しく機能します。ただし、(転送された参照を使用して生成された) bannerWidth を Banner コンポーネントの兄弟に渡すことができるように、参照を親コンポーネントに配置する必要があります。
助けていただければ幸いです:D