Front-end/React
[React]리액트 useRef 사용법
영벨롭
2022. 5. 29. 18:18
[ useRef ]
import { useRef } from "react";
const refContainer = useRef(initialValue);
<컴포넌트 ref={refContainer}></컴포넌트>
useRef는 매번 렌더링을 할 때 동일한 ref 객체를 제공합니다.
즉, 리렌더링 하지 않고 가상 DOM에서 컴포넌트의 속성을 조회&조작하고 그 결과물만 실제 DOM으로 전달합니다.
useRef는 current 속성을 가지고 있는 ref 객체를 반환하는데, 인자로 넘어온 initialValue를 current 속성에 할당합니다.
이 current 속성은 값을 변경해도 상태를 변경할 때 처럼 리액트 컴포넌트가 리렌더링되지 않고, 컴포넌트가 리렌더링될 때에도 current 속성 값은 유실되지 않습니다.
[ 예제1 - 입력창에 자동 focus ]
다음 예제는 제목과 본문을 작성할 수 있는 입력창을 구현한 모습입니다.
// src/Input.jsx
import React, { useState, useRef, useEffect } from 'react';
const Input = () => {
const [input, setInput] = useState({
title: '',
contents: ''
});
const {title, contents} = input;
const onChange = (e) => {
const {value, name} = e.target;
setInput({
...input,
[name]: value
})
};
return (
<>
<input type="text"
name="title"
value={title}
placeholder="제목을 입력해주세요"
onChange={onChange} />
<br/>
<textarea
name="contents"
value={contents}
cols="30"
rows="10"
onChange={onChange}></textarea>
</>
);
};
export default Input;
위 코드에 useRef를 사용하여 페이지가 리렌더링 될때마다 제목 입력창에 focus가 자동으로 되고, 제목을 입력한 후 엔터키를 누르면 본문 입력창에 focus 되도록하겠습니다.
먼저 useRef를 사용하여 ref 객체를 생성한뒤, ref 속성을 통해 ref 객체를 연결합니다.
// src/Input.jsx
...
const titleInput = useRef();
const contentsInput = useRef();
...
<input type="text"
name="title"
value={title}
placeholder="제목을 입력해주세요"
onChange={onChange}
ref={titleInput} // ref
onKeyUp={onKeyUp} />
<br/>
<textarea
name="contents"
value={contents}
cols="30"
rows="10"
onChange={onChange}
ref={contentsInput}></textarea> // ref
콘솔창에 titleInput.current와 contentsInput.current 를 출력해보겠습니다!
ref 객체가 잘 연결된 것을 확인할 수 있습니다.
이제 useEffect 훅을 사용하여 페이지가 리렌더링 될 때 제목 입력창을 focus합니다.
useEffect(()=>{
titleInput.current.focus();
}, [])
제목을 입력한 뒤 엔터키를 누르면 본문 입력 창에 focus를 가도록 하기 위해, onKeyUp 이벤트 콜백함수를 작성합니다.
const onKeyUp = (e) => {
if(e.key === 'Enter'){
contentsInput.current.focus();
}
}
[ 예제2 - 사용자 이름 입력받기 ]
// App.jsx
import React, { useState, useEffect, useRef, useMemo } from 'react';
import UserList from './UserList';
import AddUser from './AddUser';
const users = [
{
id: 1,
name: 'neo'
},
{
id: 2,
name: 'lion'
}
]
const App = () => {
const [data, setData] = useState(users)
const [name, setName] = useState('')
const userID = useRef(3);
const nameInput = useRef();
const onChange = (e) => {
const { value } = e.target;
setName(value);
}
const onSubmit = () => {
console.log('submit!')
const newUser = {
id: userID.current,
name: name
}
console.log(newUser)
setData([...data, newUser]);
setName('');
nameInput.current.focus();
userID.current += 1;
}
useMemo(()=>{console.log('data', data)}, [data]);
return (
<div>
<AddUser name={name} onChange={onChange} nameInput={nameInput} onSubmit={onSubmit} />
<UserList users={data} />
</div>
);
};
export default App;
// AddUser.jsx
import React, { useEffect } from 'react';
const AddUser = ({name, onChange, nameInput, onSubmit}) => {
useEffect(()=>{
nameInput.current.focus();
}, []);
return (
<>
<input type="text"
name="name"
value={name}
onChange={onChange}
ref={nameInput}
/>
<button type="button" onClick={onSubmit}>작성</button>
</>
);
};
export default AddUser;
// UserList.jsx
import React from 'react';
const UserList = ({ users }) => {
return (
<div>
{users.map((user) => (
<p key={user.id}>id: {user.id} | 이름: {user.name} </p>
))}
</div>
);
};
export default UserList;
반응형