온라인 강의/React 완벽 가이드 [Udemy]

115. "ref"로 작업하기

유호야 2023. 6. 7. 22:27
반응형

 

ref는 매우 강력한 도구로 가장 기본적인 기능은 다른 DOM 요소에 접근해서 그것들로 작업할 수 있게 해주는 것이다

 

 

폼을 제출할 때만 필요한데도

키를 입력할 때마다 state를 업데이트한다는 건

약간 과한 것 같지 않은가? 

이럴 때 ref 를 사용할 수 있다. 

 

useRef 훅을 사용해보자

모든 리액트 훅과 마찬가지로, useRef도

함수형 컴포넌트 안에서만 사용가능합니다

useRef도 초기화하려는 기본값이 필요하다

 

제가 관심있는 건 무엇을 반환하는지입니다

왜냐하면 나중에

해당 ref와 작업할 수 있게 해주는 값을 반환하기 때문입니다

즉 요소에 연결하여 해당 요소와

작업할 수 있게 해주는 거죠

 

 컴포넌트 안에 이렇게 useRef 훅을 이용해서 const 변수를 하나 생성하고 
ref를 HTML 요소에 연결하고 싶다고 React에 전달해야 한다. 

  const nameInputRef = useRef();
  const ageInputRef = useRef();

 

ref를 연결하려는 해당 요소로 이동하여 거기에 특별한 프롭인 ref 프롭을 추가하면 된다 

<input type="text" value={userName} onChange={usenameChangeHandler} ref={nameInputRef} />

 

 

console.log(nameInputRef); 를 하게 되면 
DOM 객체가 하나 반환된다 하지만 그 객체는 조작하지 않는 편이 좋다

DOM은 리액트에 의해서만 조작되어야 한다 (번거로운 작업을 위해 리액트를 사용하기 때문에)

 

 

예를 들어 값을 빠르게 읽고 싶을 때가 있을 텐데, 값만 읽고 싶다면 아무 것도 바꿀 계획이 없다면 state는 그리 필요 없다

state를 키 로그 기록용으로 사용하는 건 별로 좋지 않다

불필요한 코드와 작업이 많기 때문에 값만 읽고 싶다면 ref가 더 낫다 

 

하지만 이 프로젝트 같은 경우에는 원하는 대로 선택하면 된다

ref는 코드가 조금 더 적지만 DOM을 조작한다는 상당히 예외적인 일을 해야 하고. state는 확실히 더 깔끔하지만 코드를 조금 더 많이 써야 한다. 여러분이 결정하면 되지만 이 코스에서는 ref를 쓸 계획이다.

 

UserForm.js

import "./UserForm.css";
import { useState, useRef } from 'react';
import Card from './UI/Card';
import Button from "./UI/Button";
import ErrorModal from "./UI/ErrorModal";
import Wrapper from '../Helpers/Wrapper';

const UserForm = (props) => {
  const nameInputRef = useRef();
  const ageInputRef = useRef();

  const [userName, setUserName] = useState("");
  const [userAge, setUserAge] = useState(0);
  const [userInfo, setUserInfo] = useState([]);
  const [error, setError] = useState();

  const usenameChangeHandler = (event) => {
    setUserName(event.target.value);
  }

  const useageChangeHandler = (event) => {
    setUserAge(Number(event.target.value));
  }

  const addUserInfoHandler = (event) => {
    event.preventDefault();
    console.log(nameInputRef);
    if (userName.trim().length === 0 || userAge.length === 0) {
      setError({
        title: 'Invalid input',
        message: 'Please enter a valid name and age (non-empty values).'
      });
      return;
    }
    if (userAge < 1) {
      setError({
        title: 'Invalid input',
        message: 'Please enter a valid age (> 0).'
      });
      return;
    }
    const userInfo = {
      'userName': userName,
      'userAge': userAge,
      'userId': Math.round(Math.random() * 1000000)
    }
    props.onSaveUserInfo(userInfo);

    setUserName("");
    setUserAge("");

  }

  const errorHandler = () => {
    setError(null);
  }

  return (
    <Wrapper>
      {error && <ErrorModal title={error.title} message={error.message} onConfirm={errorHandler} />}
      <Card className="userform__container">
        <form className="userform__inner" onSubmit={addUserInfoHandler}>
          <div className="userform__box">
            <label>Username</label>
            <input type="text" value={userName} onChange={usenameChangeHandler} ref={nameInputRef} />
          </div>
          <div className="userform__box">
            <label>Age (Years)</label>
            <input type="number" value={userAge} onChange={useageChangeHandler} ref={ageInputRef} />
          </div>
          <Button type="submit">Add User</Button>
        </form>
      </Card >
    </Wrapper>
  );
}
export default UserForm;
반응형