[Udemy] React 기본 - 일기장 만들기(2)

React 기본 (Project)

Udemy - 한입크기로 잘라 먹는 리액트


📌 일기장 만들기 (2)

src/App.js

import "./App.css";
import DiaryEditor from "./DiaryEditor";

const App = () => {
  return (
    <div className="App">
      <DiaryEditor />
    </div>
  );
};
export default App;

src/DiaryEditor.js

☑️ 사용자 입력을 받는 form (input, textarea) 요소에 특정 길이 이상의 입력이 제대로 들어왔는지 확인하는 코드 작성

☑️ const handleSubmit : 일기 저장하기 버튼을 눌렀을 때 수행되는 함수를 수정

☑️ 작성자란(input)에 1글자 미만, 일기본문(textarea)가 5글자 미만일 경우 조건 추가 (alert)

  const handleSubmit = () => {
    if(state.author.length < 1) {
      alert("작성자는 최소 1글자 이상 입력해주세요.");
      return; // 더 이상 출력되지 않도록
    }

    if(state.content.length < 5){
      alert("일기 본문은 최소 5글자 이상 입력해주세요.");
      return; // 더 이상 출력되지 않도록 
    }

    alert("저장 성공!");
  };

☑️ UX 개선 : alert 대신 글자 수 미만인 경우 form 요소에 focus 주기

  • 어떤 DOM Element에 focus를 줘야 하는지?

☑️ useRef import

import { useState, useRef } from "react";

☑️ focus 해야하는 form 요소에 쓰일 상수 2개를 만들고 useRef() 호출

const authorInput = useRef();
const contentInput = useRef();

☑️ React.MutableRefObject : HTML DOM 요소에 접근할 수 있는 기능을 함

  • ref={} : reference 객체를 통해서 DOM에 접근할 수 있게 됨
  return (
    <div className="DiaryEditor">
      <h2>오늘의 일기</h2>
      <div>
        <input ref={authorInput} name="author" value={state.author}
          onChange={handleChangeState} />
      </div>
      <div>
        <textarea ref={contentInput} name="content" value={state.content}
          onChange={handleChangeState} />
      </div>
    </div>
  );

☑️ const handleSubmit에 포커스 추가 current.focus()

  • useRef 기능으로 생성한 DOM 요소를 선택하는 reference 객체는 현재를 가리키는 값을 current 프로퍼티로 불러와서 사용할 수 있음
  • authorInput.current와 contentInput.current는 모두 tag가 되고, tag에 focus되도록 만든 것임
  const handleSubmit = () => {
    if(state.author.length < 1) {
      // focus
      authorInput.current.focus();
      return;
    }

    if(state.content.length < 5){
      // focus
      contentInput.current.focus();
      return;
    }

    alert("저장 성공!");
  };

📝 Result

import { useState, useRef } from "react";

const DiaryEditor = () => {

  const authorInput = useRef();
  const contentInput = useRef();

  const [state, setState] = useState({
    author: "",
    content: "",
    emotion: 1,
  });

  const handleChangeState = (e) => {
    setState({
      ...state,
      [e.target.name]: e.target.value,
    });
  };

  const handleSubmit = () => {
    if(state.author.length < 1) {
      // alert("작성자는 최소 1글자 이상 입력해주세요.");
      // focus
      authorInput.current.focus();
      return;
    }

    if(state.content.length < 5){
      // alert("일기 본문은 최소 5글자 이상 입력해주세요.");
      // focus
      contentInput.current.focus();
      return;
    }

    alert("저장 성공!");
  };

  return (
    <div className="DiaryEditor">
      <h2>오늘의 일기</h2>
      <div>
        <input ref={authorInput} name="author" value={state.author}
          onChange={handleChangeState} />
      </div>
      <div>
        <textarea ref={contentInput} name="content" value={state.content}
          onChange={handleChangeState} />
      </div>
      <div>
        <select name="emotion" value={state.emotion} onChange={handleChangeState}>
          <option value={1}>1</option>
          <option value={2}>2</option>
          <option value={3}>3</option>
          <option value={4}>4</option>
          <option value={5}>5</option>
        </select>
      </div>
      <div>
        <button onClick={handleSubmit}>저장하기</button>
      </div>
    </div>
  );
};

export default DiaryEditor;

메일함에 보니 유데미에서 중간중간 학습 피드백을 주는 거 같다.
16시간 = 1,000분으로 환산하니 많이 들은 거 같아 괜히 뿌듯 🎉
(동기부여😊)

좋은 웹페이지 즐겨찾기