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

116. 제어되는 컴포넌트와 제어되지 않는 컴포넌트

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

지난 번에 ref를 이용한 파일을 완성

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();
    const enteredName = nameInputRef.current.value;
    const enteredAge = ageInputRef.current.value;
    if (enteredName.trim().length === 0 || enteredAge.length === 0) {
      setError({
        title: 'Invalid input',
        message: 'Please enter a valid name and age (non-empty values).'
      });
      return;
    }
    if (enteredAge < 1) {
      setError({
        title: 'Invalid input',
        message: 'Please enter a valid age (> 0).'
      });
      return;
    }
    const userInfo = {
      'userName': enteredName,
      'userAge': enteredAge,
      'userId': Math.round(Math.random() * 1000000)
    }
    props.onSaveUserInfo(userInfo);

    nameInputRef.current.value = "";
    ageInputRef.current.value = "";
  }

  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 id="username" type="text" ref={nameInputRef} />
          </div>
          <div className="userform__box">
            <label>Age (Years)</label>
            <input id="age" type="number" ref={ageInputRef} />
          </div>
          <Button type="submit">Add User</Button>
        </form>
      </Card >
    </Wrapper>
  );
}
export default UserForm;

 

대본 

지난 강의에서는
ref에 대해 배웠습니다
여러분에게 보여드렸었죠
ref로 인풋 필드에 접근하여
사용자 입력을 얻는 방법을 보여드렸었습니다
또한 조금 편법적인
방법도 보여드렸는데요
인풋 필드를 조작하고 재설정하는 방법이었죠
여러분이 그렇게 하고 싶다면요
그런데 ref를 사용하여
DOM 요소, 특히 입력 요소와
상호 작용하는 이 방법에는, 특별한 이름이 있습니다
제어되지 않는 컴포넌트라는 건데요
ref로 값에 접근하는 경우라면요
즉, 여기의 입력 컴포넌트는
제어되지 않는 컴포넌트가 됩니다
왜 '제어되지 않는'이라고 할까요?
왜냐하면 이것들은 내부 state이기 때문에
이것들 안으로 반영되는 값은
리액트에 의해 제어되지 않습니다
우리는 기본적인 인풋 작동법을 따르고 있습니다
사용자가 무언가를 입력할 수 있고
입력된 값이 반영됩니다
단지 그것을 가져오는 거죠, 리액트 기능을 사용하는 건 맞지만
하지만 인풋에 데이터를 다시 보내진 않아요
여기에서 해당 인풋에 새 값을 설정하면
이 해결법을 쓰면
리액트는 절대 사용되지 않습니다
ref를 사용하고 있긴 하지만
하지만 그건
네이티브 DOM 요소에 접근하기 위한 거죠
그런 다음 일반 DOM API를 사용해서
인풋 DOM 노드의 DOM 노드 값을 설정합니다
이런 이유로 '제어되지 않은' 이라고 하는 겁니다
리액트로 이 입력 요소의 state를
제어하지 않기 때문이죠
이제 제어되지 않는 컴포넌트와 제어되는 컴포넌트에 대해
이야기할 수 있습니다
다른 컴포넌트들의 컨텍스트에서도요
그러나 가장 일반적으로
입력 컴포넌트에 대해 이야기할 때는
일반적으로 폼 컴포넌트에 대해 얘기하는 겁니다
왜냐하면 폼 컴포넌트는 기본적으로
브라우저에 의해 내부 state를 갖는 경향이 있기 때문입니다
사용자 입력을 받아 저장하고 반영하는
인풋 요소가 구성되어 있습니다
그리고 리액트 앱에서 해당 컴포넌트로 작업할 때
리액트 state를 그것에 연결하고 싶지요
그렇기 때문에
리액트에서 인풋 컴포넌트로 작업할 때
제어/제어되지 않음에 대해 이야기하는 겁니다
여기에서처럼 ref를 사용할 때는
제어되지 않은 입력 컴포넌트가 있습니다
전에 했던 접근 방식에서는
state를 관리하고
모든 키 입력에서 해당 state를 업데이트했습니다
그리고 값 프롭으로 그 state를 인풋에
다시 공급합니다
즉, ref를 추가하기 전에 했던 접근 방식이
제어된 접근 방식입니다
즉, 해당 인풋 필드는
제어된 컴포넌트라고 할 수 있습니다
내부 state가 리액트에 의해 제어되기 때문입니다
이것들은 중요한 용어들입니다
다른 리액트 개발자와 인터뷰나 토론을 하기 위해서는
기억해 두어야 하는 용어들이죠
리액트 세계에서 자주 등장하는 용어들이니까요
반응형

'온라인 강의 > React 완벽 가이드 [Udemy]' 카테고리의 다른 글

118. 모듈 소개 : 리듀서(Reducer) 사용  (0) 2023.06.07
117. 모듈 리소스  (0) 2023.06.07
115. "ref"로 작업하기  (0) 2023.06.07
114. 포털 작업하기  (0) 2023.06.07
113. 리액트 포털 소개  (0) 2023.06.07