state로 입력에 반응

홍준섭·2023년 6월 3일

react

목록 보기
23/29

React는 UI를 조작하는 선언적 방법을 제공한다. UI의 개별 부분을 직접 조작하는 대신 구성 요소가 있을 수 있는 다양한 state를 설명하고 사용자 입력에 응답하여 state간에 전환한다.

선언적 UI와 명령형 UI의 차이점

명령형 UI는 UI를 조작하기 위한 정확한 지침을 작성해야 한다. 각 요소를 명령하여 컴퓨터에 UI 업데이트 방법을 알려야 하기 때문에 명령형이라고 한다. UI를 조작하는 것은 격리된 예제에 대해 충분히 잘 작동하지만 더 복잡한 시스템에서는 관리하기가 기하급수적으로 어려워진다.
React는 이 문제를 해결하기 위해 만들어졌다. React에서는 UI를 직접 조작하지 않는다. 대신 표시하려는 것을 선언하면 React가 UI를 업데이트하는 방법을 알아낸다.

UI를 선언적으로 생각하기

  1. 컴포넌트의 다양한 시각적 상태 식별
  2. 상태변경을 트리거 하는 요소를 결정
  3. useState를 사용하여 메모리의 state를 나타낸다
  4. 중요하지 않은 state 제거
  5. 이벤트 핸들러를 연결하여 state 설정

컴퓨넌트의 다양한 시각적 상태 식별

먼저 사용자가 볼 수 있는 UI의 다양한 상태를 모두 시각화해야 한다

  • 비어있음
  • 입력
  • 제출 중
  • 성공
  • 오류
export default function Form({
  // Try 'submitting', 'error', 'success':
  status = 'empty'
}) {
  if (status === 'success') {
    return <h1>That's right!</h1>
  }
  return (
    <>
      <h2>City quiz</h2>
      <p>
        In which city is there a billboard that turns air into drinkable water?
      </p>
      <form>
        <textarea disabled={
          status === 'submitting'
        } />
        <br />
        <button disabled={
          status === 'empty' ||
          status === 'submitting'
        }>
          Submit
        </button>
        {status === 'error' &&
          <p className="Error">
            Good guess but a wrong answer. Try again!
          </p>
        }
      </form>
      </>
  );
}

이러한 상태 변경을 트리거하는 요소를 결정한다

  • 버튼 클릭, 필드 입력, 링크 탐색과 같은 사람의 입력
  • 네트워크 응답 도착, 시간 초과 완료, 이미지 로드와 같은 컴퓨터 입력
    두 경우 모두 UI를 업데이트 하려면 상태변수를 설정해야 한다.
    예시
  • 텍스트 입력을 변경하면 텍스트 상자가 비어 있는지 여부에 따라 비어 있음 상태에서 타이핑 상태로 또는 그 반대로 전환되어야 한다
  • 제출 버튼을 클릭하면 제출 중 상태로 전환된다
  • 성공적인 네트워크 응답은 이를 성공 상태로 전환해야 한다
  • 실패한 네트워크 응답은 일치하는 오류 메세지와 함께 오류 상태로 전환해야 한다.

useState를 사용하여 메모리의 상태를 나타낸다

const [isEmpty, setIsEmpty] = useState(true);
const [isTyping, setIsTyping] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSuccess, setIsSuccess] = useState(false);
const [isError, setIsError] = useState(false);

중요하지 않은 상태 변수 제거

const [answer, setAnswer] = useState('');
const [error, setError] = useState(null);
const [status, setStatus] = useState('typing'); // 'typing', 'submitting', or 'success'

이벤트 핸들러를 연결하여 상태 설정

import { useState } from 'react';

export default function Form() {
  const [answer, setAnswer] = useState('');
  const [error, setError] = useState(null);
  const [status, setStatus] = useState('typing');

  if (status === 'success') {
    return <h1>That's right!</h1>
  }

  async function handleSubmit(e) {
    e.preventDefault();
    setStatus('submitting');
    try {
      await submitForm(answer);
      setStatus('success');
    } catch (err) {
      setStatus('typing');
      setError(err);
    }
  }

  function handleTextareaChange(e) {
    setAnswer(e.target.value);
  }

  return (
    <>
      <h2>City quiz</h2>
      <p>
        In which city is there a billboard that turns air into drinkable water?
      </p>
      <form onSubmit={handleSubmit}>
        <textarea
          value={answer}
          onChange={handleTextareaChange}
          disabled={status === 'submitting'}
        />
        <br />
        <button disabled={
          answer.length === 0 ||
          status === 'submitting'
        }>
          Submit
        </button>
        {error !== null &&
          <p className="Error">
            {error.message}
          </p>
        }
      </form>
    </>
  );
}

function submitForm(answer) {
  // Pretend it's hitting the network.
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      let shouldError = answer.toLowerCase() !== 'lima'
      if (shouldError) {
        reject(new Error('Good guess but a wrong answer. Try again!'));
      } else {
        resolve();
      }
    }, 1500);
  });
}
profile
개발 공부중입니다

0개의 댓글