😱

첫번째 문제! 삭제를 했을 때 몇 요소들의 위치가 갑자기 조정된다.

collision detection을 꺼보니 각도가 다시 계산되는 것을 발견하고 문제 해결의 실마리를 잡았다

우선 이 문제는 해결했다. 어떻게 해결했냐!! contextProvider에서 데이터의 위치를 계산해서 data초기값으로 설정해놓았는데 이게 data가 변경될때마다 Provider 함수가 불려지며 initializeNodePosition이 계속 호출되고 그것 때문에 위치들이 변경되는 거였다. 그래서 Provider안에서 initializeNodePosition(data)로 넣는 것이 아니라 Provider 바깥에서 계산을 하고 useState에 담아서 사용하는 방식으로 바꿔 해결하였습니다.

Provider{
const [data, setData] = useState(initializeNodePosition(data));
}

두번째 문제! 삭제를 했는데 삭제한 요소가 옆에 살아있는 요소에 적혀있다. 트러블 슈팅 제목처럼 양식을 삭제했는데 양식이 옆으로 전파되어 보여진다.

해당 문제는 아마도 라이브러리 상의 문제인 것으로 보인다.

react-konva가 제공하는 캔버스의 각 요소들은 얼핏 보면 jsx element로 착각할 수 있지만, 타입을 보면 KonvaNodeComponent 로 되어있다. 이는 우리가 평소에 사용하던 jsx element처럼 사용한다 해도 이와 동일한 효과를 낼 수 있는 확률이 무조건적으로 보장되어있지는 않다는 의미기도 하다.

export default function EditableText({
  id,
  text,
  isEditing,
  setIsEditing,
  offsetX,
  offsetY,
  width,
}: EditableTextProps) {
  const originalContent = text;
  const [content, setContent] = useState(originalContent);
  const { data, updateNode } = useNodeListContext();

  useEffect(() => {
    setContent(text);
  }, [text]);

  function handleTextChange(e: React.ChangeEvent<HTMLInputElement>) {
    setContent(e.target.value);
  }

  function saveContent() {
    if (content.trim()) updateNode(id, { ...data[id], keyword: content });
    else setContent(originalContent);
    setIsEditing(false);
  }

  function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if (e.key === "Enter") saveContent();
  }

  function handleBlur() {
    saveContent();
  }

  return (
    <>
      {isEditing ? (
        <EditableTextInput
          value={content}
          onChange={handleTextChange}
          onKeyDown={handleKeyDown}
          onBlur={handleBlur}
          offsetX={offsetX}
          offsetY={offsetY}
          width={width}
        />
      ) : (
        <Text
          text={content}
          fill="black"
          wrap="word"
          align="center"
          fontStyle="bold"
          offsetX={offsetX}
          offsetY={offsetY}
          width={width}
        />
      )}
    </>
  );
}

문제의 코드는 이 곳이다.

텍스트가 비었을 때 되돌리기 위해서 originalText라는 변수를 따로 할당해놓았고, 해당 원시값을 useState에 넣어 상태로 관리하면서 input을 관리할 수 있도록 하였다.

하지만 data들이 바뀌면서 다시금 렌더링이 되는 타이밍에서 요소들의 text가 삭제한 요소들의 텍스트로 바뀌는 문제가 생겼다.

상태는 따로 변경 없이 들고 있었는데, 갑자기 기존의 데이터가 바뀌면서 이를 제대로 인지하지 못한 채, 마치 데이터가 하나씩 밀려나가는 현상을 보여주었다. 이에 대해서 여러가지 추측을 해 보았는데,

  1. setter가 비동기적으로 동작하는 만큼, state가 바로 업데이트 되지 않아 요소들이 밀려난 것처럼 보인다
    1. 요소는 이미 삭제가 되었는데 데이터를 다루는 state는 바뀌지 않아서라고 하기에는 요소를 미리 만들어놓고 softDelete하는 것이 아니라 데이터 상태에 따라 렌더링 시키도록 해놓은 지라 해당 문제라고는 생각되지 않는다.
  2. 라이브러리 상의 문제이다

등등…

아마 현재는 2번이라고 생각한다. 이에 대해서는 더 알아볼 필요가 있을 것 같다.

data를 의존성 배열에 담았는데 deleteNode했을 때, data가 변하지 않는다?