그럼에도 불구하고

👨‍💻

[React] useRef란? 본문

React/React basics

[React] useRef란?

zenghyun 2023. 4. 6. 22:52

오늘은 useRef에 대해 알아보겠습니다.

 

[ useRef ] 

useRef는  current 프로퍼티로 전달된 인자 (initialValue)로 초기화된 변경 가능한 ref 객체를 반환합니다.

반환된 객체는 컴포넌트의 전 생애주기를 통해 유지될 것입니다. -  React 공식 홈페이지 

 

useRef는 저장공간 또는 DOM요소에 접근하기 위해 사용되는 React Hook이다. 여기서 Ref는 reference, 즉 참조를 뜻합니다.

 

우리가 자바스크립트를 사용할 때에는, 우리가 특정 DOM을 선택하기 위해서 querySelector 등의 함수를 사용했습니다.

 

React를 사용하는 프로젝트에서도 가끔씩 DOM을 직접 선택해야 하는 상황이 필요합니다. 그럴 때 우리는 useRef라는 React Hook을 사용합니다. 

 


 

공식문서에서 말하는 

 

Ref를 사용해야 할 때는 다음과 같습니다.

 

1. 포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때

2. 애니메이션을 직접적으로 실행시킬 때

3. 서드 파티 DOM 라이브러리를 React와 같이 사용할 때 

 

[ 예시 ]

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import React, { useState } from "react";
 
import Button from "../UI/Button";
import Card from "../UI/Card";
import ErrorModal from "../UI/ErrorModal";
 
import classes from "./AddUser.module.css";
 
const AddUser = props => {
  const [enteredUsername, setEnteredUsername] = useState("");
  const [enteredAge, setEnteredAge] = useState("");
  const [error, setError] = useState("");
 
  const addUserHandler = (event=> {
    event.preventDefault();
    if (enteredUsername.trim().length === 0 || enteredAge.trim().length === 0){
        setError({
            title: 'Invaild input',
            message: 'Please enter a valid name and age (non-empty values).'
        });
        return;
    }
    if (+enteredAge < 1) {
        setError({
            title: 'Invaild age',
            message: 'Please enter a valid age (> 0).'
        });
        return;
    }
    props.onAddUser(enteredUsername, enteredAge);
    setEnteredUsername('');
    setEnteredAge('');
  };
 
  const usernameChangeHandler = (event=> {
    setEnteredUsername(event.target.value);
  };
 
  const ageChangeHandler = (event=> {
    setEnteredAge(event.target.value);
  };
 
  const errorHandler = () => {
    setError(null);
  }
 
  return (
      <div>
      {error && <ErrorModal title={error.title} message={error.message} onConfirm={errorHandler} /> }
    <Card className={classes.input}>
      <form onSubmit={addUserHandler}>
        <label htmlFor="username">Username</label>
        <input
          id="username"
          type="text"
          value={enteredUsername}
          onChange={usernameChangeHandler}
        ></input>
        <label htmlFor="age">Age (Years)</label>
        <input id="age" type="number" value={enteredAge} onChange={ageChangeHandler}></input>
        <Button type="submit">Add User</Button>
      </form>
    </Card>
    </div>
  );
};
 
export default AddUser;
 
cs

 

위의 코드는 이름과 나이를 입력할 수 있는  input에 값을 넣고  Add User 버튼을 누르면 userLIst에 해당 값들이 출력되는 코드입니다. 

 

여기서 각각의 input 태그에는 onChange={usernameChangeHandler}와  onChange={ageChangeHandler}를 통해 값이 전달되고 있습니다. 이때 useState를 사용하는데 DOM구조를 건드리지 않고 단지 속성 값만 변경되기 때문에 useState를 사용하는 것이 과하다고 느껴질 수 있습니다. 

 

 

위의 코드는 다음과 같이 변경하여 사용할 수 있습니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import React, { useState, useRef } from "react";
 
import Button from "../UI/Button";
import Card from "../UI/Card";
import ErrorModal from "../UI/ErrorModal";
import Wrapper from "../Helpers/Wrapper";
 
import classes from "./AddUser.module.css";
 
const AddUser = props => {
  const nameInputRef = useRef();
  const ageInputRef = useRef();
 
  const [error, setError] = useState("");
 
  const addUserHandler = (event=> {
    event.preventDefault();
    const enteredName = nameInputRef.current.value;
    const enteredUserAge = ageInputRef.current.value;
 
    if (enteredName.trim().length === 0 || enteredUserAge.trim().length === 0){
        setError({
            title: 'Invaild input',
            message: 'Please enter a valid name and age (non-empty values).'
        });
        return;
    }
    if (+enteredUserAge < 1) {
        setError({
            title: 'Invaild age',
            message: 'Please enter a valid age (> 0).'
        });
        return;
    }
    props.onAddUser(enteredName, enteredUserAge);
    nameInputRef.current.value = '';
    ageInputRef.current.value = '';
   
  };
 
 
  const errorHandler = () => {
    setError(null);
  }
 
  return (
      <Wrapper>
      {error && <ErrorModal title={error.title} message={error.message} onConfirm={errorHandler} /> }
    <Card className={classes.input}>
      <form onSubmit={addUserHandler}>
        <label htmlFor="username">Username</label>
        <input
          id="username"
          type="text"
          ref={nameInputRef}
        ></input>
        <label htmlFor="age">Age (Years)</label>
        <input 
          id="age" 
          type="number" 
          ref={ageInputRef}
          ></input>
        <Button type="submit">Add User</Button>
      </form>
    </Card>
    </Wrapper>
  );
};
 
export default AddUser;
 
cs

 

name과 age를 useState를 사용하지 않고 useRef를 사용하여 name과 age의 값을 전달 및 갱신하고 있습니다. 

 

 

 const nameInputRef = useRef();
 const ageInputRef = useRef();
 
 const enteredName = nameInputRef.current.value;
 const enteredUserAge = ageInputRef.current.value;
 
 
<input
   id="username"
   type="text"
   ref={nameInputRef}    
></input>

 <input 
    id="age" 
    type="number"   
    ref={ageInputRef}
 ></input>

'React > React basics' 카테고리의 다른 글

[React] useReducer란?  (0) 2023.04.08
[React] useEffect란?  (0) 2023.04.07
[React] Portal이란?  (0) 2023.04.06
[React] htmlFor란?  (0) 2023.04.06
[React] Styled Component란?  (0) 2023.04.04
Comments