input에 todo를 입력하고 Submit하면, 아래 리스트에 todo가 추가되는 간단한 리액트 앱을 만들고 있는데,
DOM 요소에서 값을 가져오는 과정에 의문이 생겼다.
DOM API
사용을 고민하다가 useRef
를 사용하고, 최종적으로 state
로 변경했다.
import React, { useRef } from 'react';
import { v4 as uuid } from 'uuid';
export default function AddForm({ todos, setTodos }) {
const todoRef = useRef(null); // input DOM을 참조할 ref 생성
const addTodo = (event) => {
event.preventDefault();
const todo = todoRef.current.value;
setTodos((prev) => [...prev, { todo, isDone: false, id: uuid() }]);
todoRef.current.value = '';
todoRef.current.focus();
};
return (
<div className='addform__container'>
<form className='addform' onSubmit={addTodo}>
<label className='addform__label' htmlFor='new-todo'>
To Do{' '}
</label>
<input
className='addform__input'
type='text'
id='new-todo'
name='new-todo'
ref={todoRef} // todoRef가 input DOM을 참조함
autoFocus={true}
/>
<input className='btn addform__submit' type='submit' value='추가' />
</form>
</div>
);
}
addTodo
함수의 event.target
은 form이 된다.addTodo
함수에서는 input의 value를 받아와서 todo 객체를 만들고, todos 배열에 추가해야 한다.querySelector
로 input DOM을 선택하고, value 값을 가져오면 되지 않을까?useRef
라는 메소드가 있네! 이걸 사용하면 되겠다!import React, { useState } from 'react';
import { v4 as uuid } from 'uuid';
export default function AddForm({ setTodos }) {
const [todoValue, setTodoValue] = useState(''); // input value를 state로 관리, 초기값은 빈 문자열
const handleChange = (e) => {
setTodoValue(e.target.value); // input 값이 변경되면 todoValue 업데이트
};
const addTodo = (event) => {
event.preventDefault();
const todo = todoValue; // todo 추가할 때 todoValue를 바로 사용
setTodos((prev) => [...prev, { todo, isDone: false, id: uuid() }]);
setTodoValue(''); // todo 추가 완료되면 todoValue를 다시 빈 문자열로 변경
};
return (
<div className='addform__container'>
<form className='addform' onSubmit={addTodo}>
<label className='addform__label' htmlFor='new-todo'>
To Do{' '}
</label>
<input
className='addform__input'
type='text'
id='new-todo'
name='new-todo'
onChange={handleChange} // value 값이 변경되면 함수 호출
autoFocus={true} // autoFocus 속성으로 submit 후 자동 포커스
value={todoValue} // value를 todoValue로 지정 -> todo 추가 완료 후 빈 문자열로 변경
/>
<input className='btn addform__submit' type='submit' value='추가' />
</form>
</div>
);
}
ref를 사용하는 대신 input의 value를 state로 관리하도록 변경했다.
DOM에 직접 접근하지 않아도 되어 훨씬 간단하고 보기에도 깔끔한 코드가 되었다.
그러나,,, input 이벤트가 발생할 때마다 handleChange
함수를 호출하는 것이 과연 바람직한 로직인지? 의문이 들기는 한다.
이건 튜터님께 물어봐야겠다!
+ 튜터님께 물어본 결과,,, 현업에서도 굉장히 많이 쓰이는 방식이라고 한다.
Ref보다는 확실히 효율적인 방법인거 같으니 걱정말고 사용해야지!