[JS] ํน์ ์์ ์์น๋ก ์คํฌ๋กค ์ด๋ํ๊ธฐ - scrollIntoView
๋ฐ์ํ
๋ฌธ๋ฒ
ํน์ ์์๊ฐ ์์นํ ๊ณณ๊น์ง ์คํฌ๋กค์ ์ด๋ํ๊ณ ์ถ์ ๋ element.scrollIntoView
๋ฉ์๋๋ฅผ ์ด์ฉํ๋ฉด ๊ฐํธํ๊ฒ ๊ตฌํํ ์ ์๋ค. scrollIntoView
๋ฉ์๋๋ ์ด 3๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค. (MDN)
element.scrollIntoView(align)
โถ ํ๋ผ๋ฏธํฐ ์์ — element๊ฐ ๋ธ๋ผ์ฐ์ ํ๋ฉด ๊ฐ์ฅ ์๋ก ์ค๋๋ก ์คํฌ๋กค(์ ๋ ฌ)
element.scrollIntoView(); // element.scrollIntoView(true)์ ๋์ผ
โท boolean ํ๋ผ๋ฏธํฐ
// { block: "start", inline: "nearest" } ์ต์
๊ณผ ๋์ผ
element.scrollIntoView(true);
// { block: "end", inline: "nearest" } ์ต์
๊ณผ ๋์ผ
element.scrollIntoView(false);
true
๋ฅผ ๋๊ฒผ์ ๋ : element๊ฐ ๋ธ๋ผ์ฐ์ ํ๋ฉด ๊ฐ์ฅ ์๋ก ์ค๋๋ก ์คํฌ๋กค(์ ๋ ฌ)false
๋ฅผ ๋๊ฒผ์ ๋ : element๊ฐ ๋ธ๋ผ์ฐ์ ํ๋ฉด ๊ฐ์ฅ ์๋๋ก ์ค๋๋ก ์คํฌ๋กค(์ ๋ ฌ)
โธ ์ต์ ๊ฐ์ฒด ํ๋ผ๋ฏธํฐ
element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' });
behavior
: ์คํฌ๋กค ์ ํ ํจ๊ณผ (๊ธฐ๋ณธ๊ฐauto
)
์ต์ :auto
,smooth
block
: ์์ง ์ ๋ ฌ (๊ธฐ๋ณธ๊ฐstart
)
์ต์ :start
,end
,center
,nearest
inline
: ์ํ ์ ๋ ฌ (๊ธฐ๋ณธ๊ฐnearest
)
์ต์ :start
,end
,center
,nearest
๐ก block
, inline
์ต์
๊ฐ ์ค๋ช
start
: element๊ฐ ๋ธ๋ผ์ฐ์ ํ๋ฉด ๊ฐ์ฅ ์๋ก ์ค๋๋ก ์คํฌ๋กค(์ ๋ ฌ)end
: element๊ฐ ๋ธ๋ผ์ฐ์ ํ๋ฉด ๊ฐ์ฅ ์๋๋ก ์ค๋๋ก ์คํฌ๋กค(์ ๋ ฌ)center
: element๊ฐ ๋ธ๋ผ์ฐ์ ํ๋ฉด ์ค๊ฐ์ผ๋ก ์ค๋๋ก ์คํฌ๋กค(์ ๋ ฌ)nearest
: element์ ๊ฐ๊น์ด ๊ณณ์ผ๋ก ์คํฌ๋กค
ํจ์ ์์ฉ ์์
const moveToTop = () => document.body.scrollIntoView(true); // ์๋จ์ผ๋ก ์ด๋
const moveToBottom = () => document.body.scrollIntoView(false); // ํ๋จ์ผ๋ก ์ด๋
์ปค์คํ ํ ์ฌ์ฉ ์์
์ปดํฌ๋ํธ โผ
// ์ปดํฌ๋ํธ ๋ณธ๋ฌธ (๋ฐฐ์ด orders, Set ๊ฐ์ฒด selectedOrderIds๋ฅผ prop์ผ๋ก ๋ฐ์)
const tableRowRefs = useRef(
orders.map(({ order_id }) => ({
id: order_id,
element: createRef<HTMLTableRowElement>(), // ref ๊ฐ์ฒด ์ฌ๋ฌ๊ฐ ์์ฑ
})),
);
useScrollIntoView({
isActive: selectedOrderIds.size === 1, // true ์ผ๋๋ง ํ์ฑํ
ref: tableRowRefs.current.find(({ id }) => id === [...selectedOrderIds][0])
?.element,
align: { behavior: 'smooth', block: 'center' }, // align ์ต์
});
return (
<div>
{orders.map((order, i, { length }) => (
<div ref={tableRowRefs.current[i].element}>{/* ... */}</div>
))}
</div>
);
์ปค์คํ ํ โผ
interface Props {
isActive: boolean; // useScrollIntoView ํ
ํ์ฑํ ์ฌ๋ถ
ref: RefObject<HTMLElement> | undefined;
align?: ScrollIntoViewOptions; // scrollIntoView ๋ฉ์๋ align ์ต์
}
/** ์ฒซ ๋ ๋๋ง์๋ง ์ ํํ ์๋ฆฌ๋จผํธ๊ฐ ์์นํ ๊ณณ์ผ๋ก ์คํฌ๋กคํ๋ Hook */
export default function useScrollIntoView({ isActive, ref, align }: Props) {
const isNavigated = useRef(false); // ์์๊ฐ ์๋๊ณณ๊น์ง ์คํฌ๋กค ํ๋์ง ์ฌ๋ถ
useEffect(() => {
if (isActive && !isNavigated.current) {
ref?.current?.scrollIntoView(align);
isNavigated.current = true; // ์ฒซ ๋ ๋๋ง์๋ง ์คํฌ๋กคํ๊ธฐ ์ํด isNavigated ๊ฐ true๋ก ๋ณ๊ฒฝ
}
}, [align, isActive, ref]);
}
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
๋ฐ์ํ
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[TS] ํ์ ์คํฌ๋ฆฝํธ์์ CSS Module ์ฌ์ฉํ๊ธฐ (0) | 2024.05.11 |
---|---|
[React] falsy ๊ฐ์ ์ฌ์ฉํ ๋ฆฌ์กํธ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ์ฃผ์ํ ์ (0) | 2024.05.11 |
[React] ๋ฆฌ์กํธ Render Props ํจํด 2๊ฐ์ง ์ฌ์ฉ ๋ฐฉ๋ฒ (0) | 2024.05.11 |
[TS] ํ์ ์คํฌ๋ฆฝํธ ํ์ ๊ฐ๋ is / asserts ํค์๋ ์ฐจ์ด์ (0) | 2024.05.10 |
[DevTools] ๊ฐ๋ฐ์ ์นํ์ ์ธ ํฐ๋ฏธ๋ LS โ PLS (0) | 2024.05.10 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[TS] ํ์ ์คํฌ๋ฆฝํธ์์ CSS Module ์ฌ์ฉํ๊ธฐ
[TS] ํ์ ์คํฌ๋ฆฝํธ์์ CSS Module ์ฌ์ฉํ๊ธฐ
2024.05.11 -
[React] falsy ๊ฐ์ ์ฌ์ฉํ ๋ฆฌ์กํธ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ์ฃผ์ํ ์
[React] falsy ๊ฐ์ ์ฌ์ฉํ ๋ฆฌ์กํธ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ์ฃผ์ํ ์
2024.05.11 -
[React] ๋ฆฌ์กํธ Render Props ํจํด 2๊ฐ์ง ์ฌ์ฉ ๋ฐฉ๋ฒ
[React] ๋ฆฌ์กํธ Render Props ํจํด 2๊ฐ์ง ์ฌ์ฉ ๋ฐฉ๋ฒ
2024.05.11 -
[TS] ํ์ ์คํฌ๋ฆฝํธ ํ์ ๊ฐ๋ is / asserts ํค์๋ ์ฐจ์ด์
[TS] ํ์ ์คํฌ๋ฆฝํธ ํ์ ๊ฐ๋ is / asserts ํค์๋ ์ฐจ์ด์
2024.05.10