230613 React contentEditable 속성을 가진 요소의 커서 초기화 문제 해결하기
리액트를 이용한 TODO LIST를 만들던 중 할일을 보여주고 편집까지 되는 기능을 위해 contentEditable 속성을 가지는 요소를 만들어 값이 변경되면 useState를 통해 상태를 관리하려고 했다. 하지만 한글자를 친 이후부터는 커서가 항상 맨 앞으로 이동하는 문제가 발생했다.
문제가 되는 부분
문제가 되는 부분은 Todo 정보를 props로 받아서 useState에 초기값으로 지정하고
값을 사용하는 부분이다. 일반적으로 많이 사용하는 State 관리 방법이지만,
contentEditable에서는 커서 초기화 문제가 발생한다.
12345를 입력하면 1 -> 21 -> 321 -> 4321 -> 54321순으로 todoTitle값이 변경된다.
const TodoModal = ({ editTodo }) => {
[todoTitle,setTodoTitle] = useState(editTodo.title);
return(
<h5
className='todoModal__title'
contentEditable='true'
suppressContentEditableWarning={true}
onInput={handleInputTitle}
>
{todoTitle}
</h5>
)
}
원인과 해결방법
useState
const [state, setState] = useState(initialState);
위와 같이 커서가 초기화되어 맨 앞으로 이동하고 안보이는 이유는 useState 값이 변경되어
리액트에서 리렌더링을 하기 때문이다. 한 글자 입력할 때마다 아주 빠르게 깜빡이는 것을 볼 수 있다.
요소가 리렌더링될 때 커서 위치가 초기화되는 것이다.
useRef
이 문제를 해결하기 위해서는 contentEditable 속성 내부 값이 변경되어도 리렌더링 하지 않도록 하면 되는데, React에서는 내장 Hook으로 useRef를 제공한다. useRef는 렌더링에 필요하지 않는 값을 참조할 수 있다. useRef는 값이 변경되어도 리렌더링 되지 않는다.
const TodoModal = ({ editTodo }) => {
const todoTitle = useRef(editTodo.title);
return(
<h5
className='todoModal__title'
contentEditable='true'
suppressContentEditableWarning={true}
onInput={handleInputTitle}
>
{todoTitle.current}
</h5>
)
}
주의사항
Do not write or read ref.current during rendering. -React
리액트에서는 ref.current 값을 렌더링 중에 읽거나 쓰지 않도록 경고하고 있다.
상태를 관리하는 것은 State를 사용하도록 권장하고 있다.
'내일배움캠프' 카테고리의 다른 글
230615 express res.format()으로 Accept HTTP Header에 따라 다른 콘텐츠 응답하기 (0) | 2023.06.15 |
---|---|
230614 React 투두리스트 localStorage에 저장하기 (0) | 2023.06.14 |
230612 Nodejs http모듈로 서버 만들어보기 (0) | 2023.06.12 |
2306011 내일배움캠프 4주차 WIL (0) | 2023.06.11 |
230610 stackblitz에서 nodejs 프로젝트 npm 명령어 자동 실행하기 (0) | 2023.06.10 |