input창을 클릭하면 수정이 가능하고 다른 곳을 클릭하면 수정한 내용이 반영되는 컴포넌트
export const MyInput = ({ value, handleValueChange }) => {
const inputEl = useRef(null);
const [isEditMode, setEditMode] = useState(false);
const [newValue, setNewValue] = useState(value);
useEffect(() => {
if (isEditMode) {
inputEl.current.focus();
}
}, [isEditMode]);
useEffect(() => {
setNewValue(value);
}, [value]);
const handleClick = () => {
setEditMode(true);
};
const handleBlur = () => {
handleValueChange(newValue);
setEditMode(false);
};
const handleInputChange = (e) => {
setNewValue(e.target.value);
};
return (
<div>
{isEditMode ? (
<input
type='text'
value={newValue}
ref={inputEl}
onBlur={handleBlur}
onChange={handleInputChange}
/>
) : (
<span onClick={handleClick}>{newValue}</span>
)}
</div>
);
};
const cache = {
name: '이름을 입력하세요',
age: 0,
};
export const ClickToEdit = () => {
const [name, setName] = useState(cache.name);
const [age, setAge] = useState(cache.age);
return (
<>
<div>
<label>이름</label>
<MyInput
value={name}
handleValueChange={(newValue) => setName(newValue)}
/>
</div>
<div>
<label>나이</label>
<MyInput
value={age}
handleValueChange={(newValue) => setAge(newValue)}
/>
</div>
<div>
<div className='view'>
이름 {name} 나이 {age}
</div>
</div>
</>
);
};
사용자가 폼 요소를 클릭하거나 [tab]키를 눌러 요소로 이동하면 해당 요소가 포커스(focus)
주로 데이터 입력 준비를 의미, 포커싱이 이루어지는 순간 초기화 코드 실행 가능
autofocus : 페이지가 로드된 후 자동으로 해당 요소 포커싱
요소가 포커스를 잃는 순간
주로 데이터 입력이 완료되었음을 의미, 데이터 체크 및 데이터 저장 서버 요청 등을 실행
elem.focus() 와 elem.blur() 메서드를 사용해 요소에 포커스를 줄 수도, 제거할 수도 있음
올바르지 못한 값이 입력되었을 경우, onblur 메서드가 동작해 포커스를 다시 입력필드로 돌려놓을 수 있음
focus 이벤트는 버블링되지 않음.
이 경우 캡쳐링이나 focusin, focusout을 사용하면 이벤트 위임효과를 볼 수 있음
대부분의 요소는 기본적으로 포커스를 지원하지 않음. 그럼에도 포커스 하고 싶은 요소가 있다면 tabindex 사용 가능.