0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【React】複数のrefを扱う方法 ver.2【createRef不要】

Posted at

Reactの関数コンポーネントにおいて、refを複数扱う方法は、以下のような書き方がよく知られていると思います。

const ref = useRef<RefObject<HTMLDivElement>[]>([]);
data.forEach((_, index) => {
	ref.current[index] = React.createRef<HTMLDivElement>();
});

これとは異なる方法で複数のrefを扱う方法を発見したので、ここに残しておきます。

再帰コンポーネント

再帰コンポーネントを利用すると、createRefを使わずとも複数の要素を扱うことができます。
useRefとforwardRefを組み合わせて使う方法については、私の以前の記事を御覧ください。

const NewMultiRefSample = React.forwardRef<HTMLDivElement[], { data: string[] }>(({ data }, ref) => {
	// 今回表示する要素のref
	const divRef = useRef<HTMLDivElement>(null);
	// 次以降表示する要素のref
	const nextRef = useRef<HTMLDivElement[]>(null);
	// 今回表示する要素と、次以降表示する要素を合わせてフォワーディングする
	useImperativeHandle(ref, () => {
		const divDom = divRef.current;
		const nextDoms = nextRef.current;
		if (divDom != null && nextDoms != null) {
			return [divDom, ...nextDoms];
		} else {
			return [];
		}
	});

	const copiedData = data.concat();
	if (copiedData.length <= 0) {
		return null;
	}
	const headData = copiedData.shift();

	return (
		<>
			<div ref={divRef}>{headData}</div>
			<NewMultiRefSample ref={nextRef} data={copiedData} />
		</>
	);
});

このコンポーネントにrefを渡すと、DOMノードを配列を得られます。

const App = () => {
	const data = ["red", "blue", "yellow"];
	const refs = useRef<HTMLDivElement[]>(null);
	useEffect(() => {
		console.log(refs.current);
	});
	return <NewMultiRefSample ref={refs} data={data} />;
};

この手法の長所

この手法の長所は、親コンポーネント(サンプルのApp)と子コンポーネント(サンプルのNewMultiRefSample)の再レンダリングを切り離すことができることです。

冒頭に紹介した方法では、子コンポーネントをメモ化していたとしても、親コンポーネントが再レンダリングされるたびに、createRefで作り直されたrefが子コンポーネントに渡されてしまうため、子コンポーネントは必ず再レンダリングされてしまいました。

それに対して、この手法はuseRefしか利用しないため、親コンポーネントが再レンダリングされても子コンポーネントには同じrefが渡される、つまり子コンポーネントは再レンダリングされません。

親コンポーネントが頻繁に再レンダリングされる、または子コンポーネントのレンダリングのコストが重い場合、この手法を使うのが良いと思います。

この手法の短所

この手法の短所は、なんといっても読みにくい・理解されにくいことです。

チーム開発の場合は、むやみに利用するのは避けたほうがいいでしょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?