front-mockup(4)비밀번호 유효성에 따른 메시지

Creating the dots·2021년 11월 10일
0

project-2-느린우체통

목록 보기
4/10

controlled inputs

input 필드에 내용을 입력했을때, 입력값(value)을 상태로 저장하고, 상태가 변경하면 입력값(value)도 따라 바뀌도록 하는 것을 말한다. 즉, input 필드의 입력값과 상태의 싱크(sync)를 맞추는 것을 말한다.

//예시
const [title, setTitle] = useState("");
const [body,setBody] = useState("");
const [author, setAuthor] = useState("mario");

<form>
  <label>Blog Title</label>
  <input 
    type="text" 
    required 
    value={title}
    onChange={(e)=>setTitle(e.target.value)}
  />
  <label>Blog Body</label>
 <textarea 
    required
    value={body}
    onChange{(e)=>setBody(e.target.value)}>
 </textarea>
 <select
    value={author}
    onChange={(e)=>setAuthor(e.target.value)}>
   <option value="mario">mario</option>
   <option value="yoshi">yoshi</option>
 </select>
 <button>Add Blog</button>
</form>

debouncing

자동완성 등에 적용되는 기능이다. 구글 검색창에 검색어를 입력할때, 매 글자마다 ajax 요청을 보낸다면 그만큼 쿼리를 날리게 된다. 만약 유료 API를 사용한다면 비용이 많이 들게 될 것이다. 따라서, 유저가 글자를 입력할때, 특정 시간이 지난 후에 ajax 요청을 보내도록 할 수 있다. 유저가 쉬지 않고 글자를 입력할때에는 쿼리를 날리지 않고 글자를 치다가 잠깐 멈췄을때(0.5초 정도) 그때 쿼리를 날리도록 할 수 있다. 이 기능은 clearTimeoutsetTimeout으로 구현할 수 있다.

비밀번호를 변경할때, 새로운 비밀번호확인 비밀번호를 입력한다. 새로운 비밀번호에는 정규식으로 10~15글자인지 확인하고, 확인 비밀번호는 새로운 비밀번호와 일치하는지 확인한다. 이때, 각 부분을 매번 확인하지 않고 입력하다가 잠시 멈췄을때(0.5초), 확인하는 것을 구현하려고 했다.

그런데, 이것을 구현하면서 useEffect도 사용해야해서 같이 정리해보려고 한다.

문제상황

controlled inputs로 입력값과 상태의 sync를 잘 맞춰주었지만, useEffect를 쓰지 않고 함수로 상태를 가져오니 마지막 글자가 적용되지 않았다. 예를들어, 새로운 비밀번호 input 입력값이 'helloworld'일때, 콘솔창에 해당 상태를 찍어보면 'helloworl'까지만 찍혔다.

원인

마지막으로 변경된 입력값이 상태에는 반영되었지만,(다른 코드블록에서 콘솔로 찍어보면 잘 찍힘) 그 상태를 가져와서 정규식 함수에 적용하려고 하니 적용이 안됐다. 그래서 해결방법을 구글링해보니, useEffect로 어떠한 조건(이 경우는 passwords.newPassword)이 바뀔때마다 첫째로, 상태를 업데이트해주어야하고, 둘째로, 업데이트된 상태를 가져와 정규식 등을 활용한 함수로 검증을 해주면 된다.

해결

useEffect의 첫번째 인자로 콜백함수를 쓰고, 두번째 인자로 콜백함수가 실행될 조건을 작성해준다. 아래 첫번째 useEffect에서는 새로운 비밀번호의 상태가 변경될때마다 콜백함수를 실행시켰고, 두 번째 useEffect에서는 새로운 비밀번호가 저장된 새로운 상태인 confirmedPassword와 확인 비밀번호 상태가 변경될때 콜백함수를 실행시켰다.

  useEffect(() => {
    let timer;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      if (availablePw(passwords.newPassword)) {
        setIsAvailable("사용가능한 비밀번호입니다");
        setConfrimedPassword(passwords.newPassword);
      } else if (
        !availablePw(passwords.newPassword) &&
        passwords.newPassword !== ""
      ) {
        setIsAvailable("비밀번호는 10자리 이상 15자리 이하여야합니다");
      }
    }, 500);
  }, [passwords.newPassword]);

  useEffect(() => {
    let timer;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      if (
        matchingPw(confirmedPassword, passwords.matchingPassword) &&
        passwords.matchingPassword !== ""
      ) {
        setIsMatching("비밀번호가 일치합니다");
      } else if (
        !matchingPw(confirmedPassword, passwords.matchingPassword) &&
        passwords.matchingPassword !== ""
      ) {
        setIsMatching("비밀번호가 일치하지 않습니다");
      }
    }, 500);
  }, [confirmedPassword, passwords.matchingPassword]);

유효성 검사결과에 따른 메시지

지난 프로젝트에서는

지난 프로젝트에서는 상태에 따라 조건을 나누어 삼항연산자를 활용해서 구현했었다. 새로운 비밀번호의 경우, 인풋에 입력하지 않았을때 "아무것도 나타내지 않기", 입력하는 순간 유효성 검사를 진행해 "비밀번호는 10~15글자이어야합니다", 입력값이 유효성검사를 통과하면 "사용가능한 비밀번호입니다" 처럼 세가지 경우로 구분해야한다.

따라서, 새로운 비밀번호에 대한 디폴트 상태값 0, 입력하자마자 1, 유효성 검사 통과하면 2 등으로 구분해 {isPossiblePassword === 0 && null}, {isPossiblePassword === 1 && <span>비밀번호는 10~15글자이어야합니다</span>}, {isPossiblePassword === 2 && "사용가능한 비밀번호입니다"} 등으로 구분해서 작성해주었다.

그런데, 이렇게 하다보니 분기해줘야하는 조건이 너무 많았고, 코드도 길어져서 가독성이 떨어졌다. 그래서 이번 프로젝트에서는 다른 방식을 찾아서 적용해보려고 했다.

이번 프로젝트에서는

이번 프로젝트에서도 삼항연산자를 활용하기는 했다. 그런데, 클래스 적용 조건을 삼항연산자로 구분해 사용해서 반복 작성하는 부분이 훨씬 적어졌다. isAvailabe도 상태값으로 초기값은 "", 정규식 통과 시 상태변경함수로 "사용가능한 비밀번호입니다"로 변경하고, 통과하지 못했을때에는 "비밀번호는 10~15글자이어야합니다"로 저장된다.

따라서 isAvailable에 따라 클래스를 다르게 적용하고, isAvailable 값을 span태그에도 적용할 수 있다.

이렇게 작성해보니 하나의 변수로 클래스와 입력값까지 모두 처리할 수 있어서 편했다. 지난 프로젝트에서 한 것도 좀 더 능숙하게 다룰 수 있다면 가독성있게 쓸 수도 있었겠지만, 클래스를 만들어두어 다른 부분에도 쉽게 적용할 수 있어서 나는 이 방법이 더 쉽게 느껴졌다.

<span
  className={
    isAvailable === "사용가능한 비밀번호입니다" ? 
    "span-alert available" : 
    "span-alert unavailable"
  }>
    {isAvailable}
</span>

reference

profile
어제보다 나은 오늘을 만드는 중

0개의 댓글