- ๋ชฉํ
๋ฐ์ํ์น์์ ํน์ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ฐ๋ก ๋ฐ์ edit box๋ฅผ ๋์์ง๋ ๊ฒ
ํ์ฌ ํ๋ก๊ทธ๋จ ํ๋ฉด์ ๋ณด์ฌ์ค ์๋ ์์ผ๋ ํผ๊ทธ๋ง๋ก ๋์ถฉ ๊ทธ๋ ค๋ณด์๋ค.
โป Button๊ณผ Grid ๋ชจ๋ mui ์ฌ์ฉ
1. Button์ ref ๋ณ์๋ฅผ ์ค์ ํ๊ธฐ
const buttonRef = useRef<HTMLButtonElement>(null);
const [showTextBox, setshowTextBox] = useState(false); // true์ผ๋ edit box ๋ณด์ฌ์ง
<Button onClick={textBoxPopUp} ref={multipleButtonRef}>
Button
</Button>
{showTextBox ? (
<Grid
alignItems="top"
justifyContent="flex-end"
style={{
position: 'absolute',
top: buttonRef?.current?.getBoundingClientRect?.()?.bottom + 5 ?? undefined,
left: buttonRef?.current?.getBoundingClientRect?.()?.left ?? undefined
}}
>
<Grid item>
<textarea
className={theme.palette.mode === 'dark' ? 'ag-theme-balham-dark' : 'ag-theme-balham'}
style={{ minHeight: 270, minWidth: 200 }}
onKeyUp={handleKeyPress}
defaultValue={text.current}
/>
</Grid>
</Grid>
) : null}
multipleButtonRef?.current?.getBoundingClientRect?.()?.bottom
์ด ๋ถ๋ถ์ด ํต์ฌ์ด๋ผ๊ณ ํ ์ ์๋ค.
multipleButtonRef?.current?.getBoundingClientRect()๋ก ๋ฒํผ์ ํ์ฌ ์์น๋ฅผ ์์๋ผ ์ ์๋ค.
์ด๋ ๊ฒ ํ๋ฉด Object is possibly 'undefined'. ์ค๋ฅ๊ฐ ๋ฌ๋ค
buttonRef์ ์ด๊ธฐ๊ฐ์ด null์ด๋ค ๋ณด๋๊น ์ต์ ๋ ์ฒด์ด๋ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ์ค๋ฅ๊ฐ ๋จ๋ ๊ฒ ๊ฐ๋ค.
์ด๊ธฐ๊ฐ์ null๋ง๊ณ ๋ค๋ฅธ ๊ฑธ๋ก ์ค์ ํด์ผํ๋.. ํ๋ค๊ฐ ๋ญ๋ก ์ค์ ํด์ค์ง๋ฅผ ๋ชจ๋ฅด๊ฒ ์ด์.. ์ผ๋จ ๋ ๋๋ค ๐ฅน
์ด๊ฒ ์ ๋จนํ๋ค๋ฉด ์ ๋ง ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์์ํ ๋ฐ...
+ top: buttonRef?.current?.getBoundingClientRect?.()?.bottom + 5 ?? undefined,
์ด ๋ถ๋ถ์
top: buttonRef?.current?.getBoundingClientRect?.()?.bottom ?? 0 + 5 ?? undefined,
์ผ๋ก ๋ฐ๊ฟจ๋๋ ์ ๋จน๋๋ค!!!
+ ๊ทผ๋ฐ ๋ฌํ๊ฒ ์์น๊ฐ ์ด์ํจ..
2. Button ํด๋ฆญ ์ด๋ฒคํธ, ์ฐฝ ํฌ๊ธฐ ๋ณ๊ฒฝ ์ด๋ฒคํธ ์ด์ฉํ๊ธฐ
- ๋ฒํผ์ ํด๋ฆญํ์ ๋ ์ด๋ฒคํธ
const [textPos, setTextPos] = useState<{ mouseX: number; mouseY: number } | null>(null);
const textBoxPopUp = async (event: any) => {
const pos = event.target.getBoundingClientRect();
setTextPos({
mouseX: pos.left,
mouseY: pos.bottom + 5
});
};
<Button onClick={textBoxPopUp} ref={multipleButtonRef}>
Button
</Button>
{showTextBox ? (
<Grid
alignItems="top"
justifyContent="flex-end"
style={{
position: 'absolute',
top: textPos ? textPos.mouseY : undefined,
left: textPos ? textPos.mouseX : undefined
}}
>
<Grid item>
<textarea
className={theme.palette.mode === 'dark' ? 'ag-theme-balham-dark' : 'ag-theme-balham'}
style={{ minHeight: 270, minWidth: 200 }}
onKeyUp={handleKeyPress}
defaultValue={text.current}
/>
</Grid>
</Grid>
) : null}
์ฌ๊ธฐ์ ํต์ฌ์, textPos๋ผ๋ ๋ณ์๋ฅผ ํตํด์ text box์ ์์น๋ฅผ ๊ด๋ฆฌํ๋ค๋ ๊ฒ์ด๋ค.
- ์ฐฝ ํฌ๊ธฐ ๋ณ๊ฒฝ
useEffect(() => {
const handleWindowResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight
});
};
window.addEventListener('resize', handleWindowResize);
return () => {
window.removeEventListener('resize', handleWindowResize);
};
}, []);
useEffect(() => {
// ์ฐฝ ํฌ๊ธฐ ๋ณ๊ฒฝ
const pos = buttonRef.current?.getBoundingClientRect?.();
if (showTextBox && pos) {
setTextPos({
mouseX: pos.left,
mouseY: pos.bottom + 5
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [windowSize]);
์ฐฝํฌ๊ธฐ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค textPos๋ฅผ ๋ณ๊ฒฝํด์ค๋ค.
๋งค์ฐ ๋ถ๋๋ฝ๊ฒ ๋ณ๊ฒฝ๋์ง ์์ง๋ง.. ์ผ๋จ ๋ชฉํ ๋ฌ์ฑ !!!!
'Programming > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ React ] gsap ScrollTrigger ์ฌ์ฉ์ execute 'removeChild' on 'Node': The node to be removed is not a child of this node ์ค๋ฅ (0) | 2023.11.09 |
---|---|
[ React ] function(์ ์ธ๋ฌธ) vs const (ํํ์) (0) | 2023.07.27 |
[ React ] ๊ฐ์ ๋ ๋๋ง (0) | 2023.05.11 |
[ React ] MUI Typography ํ ์คํธ ๊ทธ๋ฆผ์ ๋ฃ๊ธฐ textShadow (0) | 2022.10.20 |
[ React ] ๊ฐ์ฒด ๊ฐ ๋ณ๊ฒฝ (0) | 2022.10.06 |