React와 Typescript를 사용한 프로젝트에서 input에 useRef를 사용하던 중 새롭게 알게된 내용을 정리했습니다.
동일한 컴포넌트에서 useRef를 사용하는 경우 이 내용이 큰 도움이 되지 않을 수 있지만,
부모 컴포넌트에서 자식 컴포넌트에 prosp로 ref를 넘기고, 해당 ref에 접근하여 DOM을 조작하거나 값을 얻어야 하는 경우에 도움이 될 듯 합니다.
실행 화면
코드
- useRef() : DOM 취득 용도로 HTMLInputElement 타입을 설정하고, 초깃값으로 null을 설정한다.
// Parent.tsx
import { useState, useEffect, useRef } from "react";
import Input from "./Input";
import Button from "../elements/Button";
interface UserInfo {
name: string;
age: number;
}
const Parent = () => {
const nameRef = useRef<HTMLInputElement>(null);
const [userInfo, setUserInfo] = useState<UserInfo>({
name: "홍길동",
age: 20,
});
useEffect(() => {
if (nameRef.current) {
nameRef.current.focus();
}
}, [nameRef]);
const inputHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
const name = e.target.name;
const value = e.target.value;
setUserInfo((prev) => {
return { ...prev, [name]: value };
});
};
const submit = () => {
alert(
`회원의 이름은 ${userInfo.name}이고, 나이는 ${userInfo.age}세입니다.`
);
};
return (
<div>
<Input
name="name"
value={userInfo.name}
onChange={inputHandler}
ref={nameRef}
/>
<Input
name="age"
value={userInfo.age}
onChange={inputHandler}
enter={submit}
/>
<Button onClick={submit}>저장하기</Button>
</div>
);
};
export default Parent;
- 부모에서 자식 컴포넌트에 props로 ref를 넘겨주면, React에 forwardRef와 ForwardedRef(type)를 import 받고, 두 번째 인자에 ref: ForwadedRef<HTMLInputElement>를 삽입하면 정상적으로 적용됩니다.
// Input.tsx
import { forwardRef, type ForwardedRef } from "react";
import styled from "@emotion/styled/macro";
interface Props {
type?: string;
value: string | number;
name: string;
onChange: any;
enter?: any;
}
const Input = forwardRef(
(
{ type = "string", value, name, onChange, enter }: Props,
ref: ForwardedRef<HTMLInputElement>
) => {
const onKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
enter();
}
};
return (
<InputWrap
type={type}
value={value}
name={name}
onChange={onChange}
onKeyPress={onKeyPress}
ref={ref}
/>
);
}
);
const InputWrap = styled.input`
width: calc(100% - 30px);
height: 49px;
text-align: left;
color: #212529;
outline: none;
border: 2px solid #eee;
background: #fbfbfb;
border-radius: 6px;
padding: 0 15px;
margin: 10px 0;
&:focus,
&:focus-visible {
border: 2px solid var(--base-color);
background: white;
}
`;
export default Input;
참고
'더 알아보기 > 기능' 카테고리의 다른 글
[Next.js] 드래그 상태에서 css 조작하기 (2) | 2023.11.23 |
---|---|
[React + Typescript] Canvas 태그와 useRef를 사용하여 그림판 만들기 (0) | 2023.10.20 |
[React-Toastify] 토스트 기능 구현해보기 (0) | 2023.09.26 |
[AWS] S3에 이미지 추가/삭제/복사(이동) 및 설정하는 방법 (0) | 2023.07.13 |
axios 여러 개 요청하기 (multiple request) (0) | 2023.03.30 |
댓글