Today Sangmin Learned
article thumbnail
728x90

오늘은 기존에 쓰던 react-simplemde-editor 마크다운 에디터를 버리고 toast-ui 에디터로 바꾸었다. 다른 건 다 그렇다 치는데 Next에서 렌더링이 안되었고 그 해결책을 찾기가 어려웠다.

 

그래서 바꾸고 난 뒤에 Next에서 사용할 수 있게끔 처리를 해서 페이지에 띄우는 데는 성공하였다.

이제, 용어의 이름과 마크다운 각각에 대해 값이 들어가있는지의 여부를 파악하는 useState Hook을 두가지 만들었다.

import React, { useState, useCallback } from 'react'

const TermRelated = () => {
  interface ITerms {
    id: number
    text: string
  }
  const [inputTerm, setInputTerm] = useState('')
  const [relatedTerms, setRelatedTerms] = useState<ITerms[]>([])
  const [contentNotFoundError, setContentNotFoundError] = useState(true)
  const [titleInputNotFoundError, setTitleInputNotFoundError] = useState(true)
  const [id, setId] = useState(1)
  
  const onClick = () => {
    // 값 추가하는 함수 (생략)
    const termsArray = relatedTerms.concat({
      // 입력한 값 배열에 추가하는 함수 (생략)
    })
    setRelatedTerms(termsArray)
    if (termsArray.length > 0) {
      setRelatedTermsNotFoundError(false)
    }
    setId(id + 1)
    setInputTerm('')
  }
    const onRemove = (id: number): void => {
    const termsArray = relatedTerms.filter(
	  // 삭제버튼 누르면 삭제하는 함수 (생략)
    )
    setRelatedTerms(termsArray)
    if (termsArray.length < 1) {
      setRelatedTermsNotFoundError(true)
    }
  }
  return (
    <>
      {!relatedTermsNotFoundError && !contentNotFoundError ? (
        <input
          css={submitButtonStyle}
          id="submit"
          type="submit"
          onSubmit={onSubmit}
          value="저장하기"
        />
      ) : (
        <input
          css={submitButtonNotReadyStyle}
          disabled={true}
          id="submit"
          type="submit"
          onSubmit={onSubmit}
          value="저장하기"
        />
      )}
    </>
  )
}

export default TermRelated

이렇게 대충 만들었다. 값이 비어있는지의 여부를 판단하기 위해서

  1. contentNotFoundError(마크다운 내부의 값이 비어있는지 확인하는 useState)
  2. titleInputNotFoundError(제목 값이 비어있는지 판단하는 useState)

이렇게 두 가지를 만들었다.

 

그리고 각각에 대해

  1. 마크다운 내부의 값의 길이(length)가 1 이상인 경우, 그러니까 값이 존재하는 경우에 contentNotFoundError를 false로 바꾸고
  2. 제목 값을 변경할 때 그 길이가 역시 1 이상이라면 setTitleInputNotFoundError를 false로 바꿨다.

그리고 저 contentNotFoundError와 titleInputNotFoundError가 모두 false일 경우, 즉 마크다운 에디터 내부와 제목 입력하는 input 두 가지 모두에 대해 값이 있는 경우에 버튼이 활성화되도록 하였다.

 

버튼의 상태 관리는 삼항 연산자를 통해서 진행했고, 두 가지 에러가 모두 false인 경우가 아니라면, 즉 하나라도 값이 비어있는 경우라면 아래쪽의 input값이 나오게 하였다. 여기서 주목할 부분은 disabled={true} 이다. 이게 true라면 버튼은 그 기능을 상실한다. 에러가 없을 경우에만 버튼이 활성화되어서 눌렀을 때 이후의 동작이 이뤄질 수 있도록 한 것이다.

 

 

예시 동영상

이 예시 동영상은 둘 다 값이 있을 때만 버튼이 활성화되도록 만든 것인데, 저 동영상을 찍을 당시에는 마크다운 에디터가 뜨지 않는 상황이었어서 대신 관련 용어 태그가 하나라도 있는지의 여부를 검사하도록 하였다.

 

그런데 문제는, 현재 마크다운 에디터의 값이 비어있는지 여부를 확인하는 useState Hook이 잘 먹지 않는다.

(...)
  const handleChange = useCallback(() => {
    if (!editorRef.current) {
      setContentNotFoundError(true)
      return
    } else {
      setContentNotFoundError(false)
      console.log(contentNotFoundError)
    }

    const instance = editorRef.current.getInstance()
    const valueType = props.valueType || 'markdown'

    props.onChange(
      valueType === 'markdown' ? instance.getMarkdown() : instance.getHTML(),
    )
  }, [props, editorRef.current])
  
  return (
    <div>
      <EditorWithForwardedRef
        {...props}
        initialValue={initialValue || 'hello react editor world!'}
        previewStyle={previewStyle || 'vertical'}
        height={height || '550px'}
        initialEditType={initialEditType || 'markdown'}
        useCommandShortcut={useCommandShortcut || true}
        ref={editorRef}
        onChange={handleChange}
      />
    </div>
  )
(...)

마크다운 컴포넌트의 일부분이다. return문에서 볼 수 있다시피 onChange에 대해 handleChange 함수에서 관리하도록 되어있다. 

그래서 handleChange 함수를 보면 useRef의 값이 비어있는지의 여부를 !editorRef.current 여부로 조사하였다. 그래서 값이 없다면 에러(useState)를 true로 설정하고 그 이후의 과정이 진행되지 않도록 하였고, 그게 아닌 경우(값이 있다면) 에러(useState)를 false로 설정하도록 한 뒤에 콘솔에 한번 출력해봤다.

근데 보다시피, 처음에 값을 지울 때는 true를 출력하지만 값을 썼다가 전부 지웠을 때도 계속 false를 출력한다. 마지막에 값을 전부 지웠을 때는 true가 떠야 정상인데 이부분이 true로 출력되지 않아서 진행을 더이상 못하고 있다. editorRef.current가 e.target.value와는 다른 역할을 하는 걸까? 좀 더 고민해봐야한다. 🤔

profile

Today Sangmin Learned

@steadily-worked

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