memostack
article thumbnail
블로그를 이전하였습니다. 2023년 11월부터 https://bluemiv.tistory.com/에서 블로그를 운영하려고 합니다. 앞으로 해당 블로그의 댓글은 읽지 못할 수 도 있으니 양해바랍니다.
반응형

Item 추가 기능 개발

우선 값을 입력받는 기능부터 개발한다.

 

input에 입력한 값 가져오기

useState()를 사용하면, input에 입력한 값을 가져올 수 있다

import React, { useState } from 'react';

const InputBox = () => {
  const [text, setText] = useState(''); // (1)

  const onChangeInput = (e) => { // (2)
    setText(e.target.value);
  };

  return (
    <div className="todoapp__inputbox">
      {/* 아이템 내용 입력 input */}
      <input
        type="text"
        name="todoItem"
        value={text}
        placeholder="할 일을 입력해주세요"
        className="todoapp__inputbox-inp"
        onChange={onChangeInput} // (3)
      />
      {/* 입력 후 아이템 추가 버튼 */}
      <button type="submit" className="todoapp__inputbox-add-btn">
        추가
      </button>
    </div>
  );
};

export default InputBox;
  • (1): useState() Hook으로 빈 문자열의 textsetText()를 생성한다.
  • (2): input이 변화하는 이벤트가 발생했을때, e.target에 있는 <input ... />으로부터 value 값을 가져오는 메소드를 생성한다.
  • (3): input이 변하는 이벤트가 발생했을때, onChangeInput() 메소드를 실행한다.

 

input 값 초기화 및 포커싱

버튼을 눌렀을때, 입력된 값을 지우고 input에 다시 focusing이 되도록한다. focusing을 할때는 useRef Hook을 사용한다.

useRef는 DOM에 직접적으로 접근할 때 사용한다
import React, { useRef, useState } from 'react';

const InputBox = () => {
  const [text, setText] = useState('');
  const inputRef = useRef(null); // (1)

  const onChangeInput = (e) => {
    setText(e.target.value);
  };

  const onClickAddButton = () => { // (2)
    setText(''); // (2-1) input 값을 초기화
    inputRef.current.focus(); // (2-2) input으로 포커싱
  };

  return (
    <div className="todoapp__inputbox">
      {/* 아이템 내용 입력 input */}
      <input
        type="text"
        name="todoItem"
        value={text}
        ref={inputRef} // (3)
        placeholder="할 일을 입력해주세요"
        className="todoapp__inputbox-inp"
        onChange={onChangeInput}
      />
      {/* 입력 후 아이템 추가 버튼 */}
      <button
        type="submit"
        className="todoapp__inputbox-add-btn"
        onClick={onClickAddButton} // (4)
      >
        추가
      </button>
    </div>
  );
};

export default InputBox;
  • (1): useRef() Hook으로 ref 생성
  • (2): 버튼을 클릭했을때, 실행되는 메소드
  • (2-1): setText('')에 빈문자열을 넣어 초기화
  • (2-2): ref.current로 <input /> 태그에 접근하여 focus()으로 포커싱한다.
  • (3): 위의 (1)에서 생성한 ref를 할당
  • (4): 버튼을 클릭했을때, onClickAddButton() 메소드를 실행한다.

 

TodoList에 아이템 추가

Home.jsx에 todoList를 생성하여 입력한 item을 담을 수 있도록 하자

import React, { useState } from 'react';
import InputBox from '../components/InputBox';
import ToDoItemList from '../components/ToDoItemList';

const Home = () => {
  const [todoList, setTodoList] = useState([]); // (1)

  return (
    <div className="homepage__container">
      {/* ToDo Item을 추가할 수 있는 input 박스 */}
      <InputBox todoList={todoList} setTodoList={setTodoList} /> {/* (2) */}

      {/* 할 일 아이템 리스트 */}
      <ToDoItemList />

      {/* 완료한 아이템 리스트 */}
      <ToDoItemList />
    </div>
  );
};

export default Home;
  • (1): useState 훅을 사용하여 todo 아이템을 담을 리스트와 setter 함수를 생성한다.
  • (2): 입력한 값을 (1)에서 생성한 리스트에 담기 위해, InputBox 컴포넌트로 todoList와 setTodoList()를 넘겨준다.

 

InputBox에서는 버튼을 눌렀을때, todoItemList에 값을 담는다.

그 전에 자식 컴포넌트에서 props 타입 검증을 위해 prop-types 모듈을 설치한다.

$ yarn add prop-types

 

이제, InputBox에 기능을 추가해보자

import React, { useRef, useState } from 'react';
import PropTypes from 'prop-types';

const InputBox = ({ todoList, setTodoList }) => { // (1)
  const [text, setText] = useState('');
  const inputRef = useRef(null);

  // input 값 가져오기
  const onChangeInput = (e) => {
    setText(e.target.value);
  };

  const onClickAddButton = () => {
    // todoItemList에 값 추가
    const nextTodoList = todoList.concat({ // (2)
      id: todoList.length, // (2-1)
      text, // (2-2)
    });
    setTodoList(nextTodoList);

    // input 값 초기화 및 포커싱
    setText('');
    inputRef.current.focus();
  };

  return (
    <div className="todoapp__inputbox">
      {/* 아이템 내용 입력 input */}
      <input
        type="text"
        name="todoItem"
        value={text}
        ref={inputRef}
        placeholder="할 일을 입력해주세요"
        className="todoapp__inputbox-inp"
        onChange={onChangeInput}
      />
      {/* 입력 후 아이템 추가 버튼 */}
      <button
        type="submit"
        className="todoapp__inputbox-add-btn"
        onClick={onClickAddButton}
      >
        추가
      </button>
    </div>
  );
};

// props 값 검증
InputBox.propTypes = {
  todoList: PropTypes.arrayOf( // (3)
    PropTypes.shape({ // (3-1)
      id: PropTypes.number.isRequired, // (3-2)
      text: PropTypes.string.isRequired, // (3-3)
    }).isRequired
  ),
  setTodoList: PropTypes.func.isRequired, // (4)
};

export default InputBox;
  • (1): 부모 컴포넌트(Home.jsx)로 부터 props로 todoListsetTodoList를 받아온다.
  • (2): input에 입력한 값을 setTodoList()를 이용하여 todoList에 추가한다.
    • concat 함수는 인자로 받은 값을 배열에 추가하여 새로운 배열을 반환한다.
  • (2-1): 각 Todo 아이템 마다 id라는 식별자를 넣는다. (식별자는 배열의 길이로 설정)
  • (2-2): 각 Todo 아이템의 내용
  • (3): 위에서 설치한 prop-types를 이용하여, props의 타입을 강제한다. todoList는 배열이어야 함
  • (3-1): todoList의 원소는 객체(object)이어야 함
  • (3-2): id 는 숫자이어야 함
  • (3-3): text 는 문자열이어야 함
  • (4): setTodoList는 함수이어야 함
prop-types에 대한 자세한 내용은 아래 글 참고
https://ko.reactjs.org/docs/typechecking-with-proptypes.html

 

기능 동작 확인

기능 동작 확인을 위해 useEffect Hook을 이용하여 콘솔에 todoItemList를 출력해보자

const InputBox = ({ todoList, setTodoList }) => {

  // ...
  
  useEffect(() => {  // todoList가 변했을때만 실행
    console.log(todoList);
  }, [todoList]);
  
  // ...
}

 

아이템이 추가되는것을 확인했고, 추가된 아이템이 목록에 보이도록 수정해보자

2021.07.13 - [React] - React로 간단한 ToDo List 만들기 (#5 할 일 목록 조회 기능 개발)

 

React로 간단한 ToDo List 만들기 (#5 할 일 목록 조회 기능 개발)

할 일 목록 조회 기능 개발 목록을 출력하기 위해, 아래와 같이 컴포넌트에 아래 props 를 넘긴다. todoList : 목록 setTodoList : 목록의 값을 조작하기 위해 title : 목록의 제목(Title) Home.jsx import React,..

memostack.tistory.com

 

전체 코드는 아래 링크에서 확인 할 수 있습니다.

https://github.com/bluemiv/react_todo_app

 

GitHub - bluemiv/react_todo_app: React로 만든 ToDo Web Application

React로 만든 ToDo Web Application. Contribute to bluemiv/react_todo_app development by creating an account on GitHub.

github.com

 
반응형
블로그를 이전하였습니다. 2023년 11월부터 https://bluemiv.tistory.com/에서 블로그를 운영하려고 합니다. 앞으로 해당 블로그의 댓글은 읽지 못할 수 도 있으니 양해바랍니다.
profile

memostack

@bluemiv_mm

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!