React의 useRef를 사용하기위한주의 사항
소개
DOM의 바운딩 박스 등을 취득하는 경우, hooks
의 useRef
를 사용하고 싶은 경우가 있습니다. 그러나, 하위의 컴퍼넌트에 그러한 정보를 건네주는 경우 등은, 주의가 필요하게 됩니다.
예
다음과 같이 메시지의 오른쪽 하단에 좋아요 버튼을 표시하고 싶습니다.

작동하지 않는 패턴
ThumbsUp
컴퍼넌트에 대해 버튼 위치의 기준이 되는 HTMLElement
를 건네주어, ThumbsUp
로 버튼의 표시 위치를 요구하고 있습니다.
App.tsximport React, { useRef } from "react";
import ThumbsUp from "./ThumbsUp";
import "./styles.scss";
export default function App() {
const ref = useRef<HTMLSpanElement | null>();
return (
<div>
<span ref={ref} className="baloon">
こんにちは
</span>
{ref.current && (
<ThumbsUp anchor={ref.current} />
)}
</div>
);
}
ThumbsUp.tsximport React, { useRef, useEffect } from "react";
import "./styles.scss";
type Props = {
anchor: HTMLElement;
};
export default function Portal({ anchor }: Props) {
const ref = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (ref.current) {
const anchorRect = anchor.getBoundingClientRect();
const position = {
top: anchorRect.top + anchorRect.height - 20,
left: anchorRect.left + anchorRect.width - 10
};
ref.current.style.top = `${position.top}px`;
ref.current.style.left = `${position.left}px`;
}
}, [anchor]);
return (
<div ref={ref} className="thumbs-up">
<button>
<span role="img" aria-label="thumbs-up">
👍
</span>
</button>
</div>
);
}
무슨 일이 일어나는가
불행히도 의도대로 좋아요 버튼이 표시되지 않습니다.

이것은 공식 에도 기재되어 있습니다만, App.tsx
에 있어서, ref.current
가 바뀌어도 재렌더는 발생하지 않기 때문입니다. 따라서 ThumbsUp
는 렌더링되지 않은 상태입니다.
해결책
콜백 식의 ref
와 useState
를 사용하는 것으로 해결할 수 있습니다. 아래와 같이 span
의 ref
에 함수를 주는 것으로, setAnchor
가 불려진 타이밍에 재렌더를 발생시켜, 의도대로 ThumbsUp
를 렌더링 할 수 있게 됩니다.
App.tsximport React, { useState } from "react";
import ThumbsUp from "./ThumbsUp";
import "./styles.scss";
export default function App() {
const [anchor, setAnchor] = useState<HTMLSpanElement>();
return (
<div>
<span
ref={elm => { // コールバック関数を与える
setAnchor(elm);
}}
className="baloon"
>
こんにちは
</span>
{anchor && <ThumbsUp anchor={anchor} /> }
</div>
);
}
Reference
이 문제에 관하여(React의 useRef를 사용하기위한주의 사항), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/mktu/items/1d1c0259ed16e9a4155a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
다음과 같이 메시지의 오른쪽 하단에 좋아요 버튼을 표시하고 싶습니다.

작동하지 않는 패턴
ThumbsUp
컴퍼넌트에 대해 버튼 위치의 기준이 되는 HTMLElement
를 건네주어, ThumbsUp
로 버튼의 표시 위치를 요구하고 있습니다.
App.tsximport React, { useRef } from "react";
import ThumbsUp from "./ThumbsUp";
import "./styles.scss";
export default function App() {
const ref = useRef<HTMLSpanElement | null>();
return (
<div>
<span ref={ref} className="baloon">
こんにちは
</span>
{ref.current && (
<ThumbsUp anchor={ref.current} />
)}
</div>
);
}
ThumbsUp.tsximport React, { useRef, useEffect } from "react";
import "./styles.scss";
type Props = {
anchor: HTMLElement;
};
export default function Portal({ anchor }: Props) {
const ref = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (ref.current) {
const anchorRect = anchor.getBoundingClientRect();
const position = {
top: anchorRect.top + anchorRect.height - 20,
left: anchorRect.left + anchorRect.width - 10
};
ref.current.style.top = `${position.top}px`;
ref.current.style.left = `${position.left}px`;
}
}, [anchor]);
return (
<div ref={ref} className="thumbs-up">
<button>
<span role="img" aria-label="thumbs-up">
👍
</span>
</button>
</div>
);
}
무슨 일이 일어나는가
불행히도 의도대로 좋아요 버튼이 표시되지 않습니다.

이것은 공식 에도 기재되어 있습니다만, App.tsx
에 있어서, ref.current
가 바뀌어도 재렌더는 발생하지 않기 때문입니다. 따라서 ThumbsUp
는 렌더링되지 않은 상태입니다.
해결책
콜백 식의 ref
와 useState
를 사용하는 것으로 해결할 수 있습니다. 아래와 같이 span
의 ref
에 함수를 주는 것으로, setAnchor
가 불려진 타이밍에 재렌더를 발생시켜, 의도대로 ThumbsUp
를 렌더링 할 수 있게 됩니다.
App.tsximport React, { useState } from "react";
import ThumbsUp from "./ThumbsUp";
import "./styles.scss";
export default function App() {
const [anchor, setAnchor] = useState<HTMLSpanElement>();
return (
<div>
<span
ref={elm => { // コールバック関数を与える
setAnchor(elm);
}}
className="baloon"
>
こんにちは
</span>
{anchor && <ThumbsUp anchor={anchor} /> }
</div>
);
}
Reference
이 문제에 관하여(React의 useRef를 사용하기위한주의 사항), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/mktu/items/1d1c0259ed16e9a4155a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
import React, { useRef } from "react";
import ThumbsUp from "./ThumbsUp";
import "./styles.scss";
export default function App() {
const ref = useRef<HTMLSpanElement | null>();
return (
<div>
<span ref={ref} className="baloon">
こんにちは
</span>
{ref.current && (
<ThumbsUp anchor={ref.current} />
)}
</div>
);
}
import React, { useRef, useEffect } from "react";
import "./styles.scss";
type Props = {
anchor: HTMLElement;
};
export default function Portal({ anchor }: Props) {
const ref = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (ref.current) {
const anchorRect = anchor.getBoundingClientRect();
const position = {
top: anchorRect.top + anchorRect.height - 20,
left: anchorRect.left + anchorRect.width - 10
};
ref.current.style.top = `${position.top}px`;
ref.current.style.left = `${position.left}px`;
}
}, [anchor]);
return (
<div ref={ref} className="thumbs-up">
<button>
<span role="img" aria-label="thumbs-up">
👍
</span>
</button>
</div>
);
}
불행히도 의도대로 좋아요 버튼이 표시되지 않습니다.

이것은 공식 에도 기재되어 있습니다만,
App.tsx
에 있어서, ref.current
가 바뀌어도 재렌더는 발생하지 않기 때문입니다. 따라서 ThumbsUp
는 렌더링되지 않은 상태입니다.해결책
콜백 식의 ref
와 useState
를 사용하는 것으로 해결할 수 있습니다. 아래와 같이 span
의 ref
에 함수를 주는 것으로, setAnchor
가 불려진 타이밍에 재렌더를 발생시켜, 의도대로 ThumbsUp
를 렌더링 할 수 있게 됩니다.
App.tsximport React, { useState } from "react";
import ThumbsUp from "./ThumbsUp";
import "./styles.scss";
export default function App() {
const [anchor, setAnchor] = useState<HTMLSpanElement>();
return (
<div>
<span
ref={elm => { // コールバック関数を与える
setAnchor(elm);
}}
className="baloon"
>
こんにちは
</span>
{anchor && <ThumbsUp anchor={anchor} /> }
</div>
);
}
Reference
이 문제에 관하여(React의 useRef를 사용하기위한주의 사항), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/mktu/items/1d1c0259ed16e9a4155a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
import React, { useState } from "react";
import ThumbsUp from "./ThumbsUp";
import "./styles.scss";
export default function App() {
const [anchor, setAnchor] = useState<HTMLSpanElement>();
return (
<div>
<span
ref={elm => { // コールバック関数を与える
setAnchor(elm);
}}
className="baloon"
>
こんにちは
</span>
{anchor && <ThumbsUp anchor={anchor} /> }
</div>
);
}
Reference
이 문제에 관하여(React의 useRef를 사용하기위한주의 사항), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/mktu/items/1d1c0259ed16e9a4155a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)