본문 바로가기
스파르타코딩클럽/내일배움캠프

[TIL] 내일배움캠프 React 과정 2022.12.25

by heereal 2022. 12. 26.

Today I Leraned

  • 팀 프로젝트 진행

 


input 입력 문제 해결

useEffect(() => {
    // 첫 렌더링 시 form help text 띄우지 않도록
    if (!userId) return ; 
    onChangeUserIdHandler()
}, [userId]);

input에 '12345'를 입력하면 '1234'로 인식하던 문제를 해결했다. useEffect를 사용해서 userId(=input value)가 변할 때마다 유효성 검사를 하는 onChangeIdHandler 함수를 실행해주라고 코드를 작성했다. 그런데 이렇게 했더니 로그인 페이지 들어가자마자 아이디 input 밑에 "아이디를 입력하세요"라는 메시지가 뜨는 게 보기 싫어서 userId에 입력된 값이 없다면 아무것도 실행하지 말아라!라는 의미로 if문을 한 줄 추가했다.

 

그런데 이렇게 하니까 콘솔에 userId가 두 번씩 찍히는데 큰 문제는 아니지만 이유가 궁금하기로 내일 튜터님께 질문하기로 한다.

 

참고 https://velog.io/@seoltang/React-setState-useEffect

 

버튼 diabled 설정하기

회원가입할 때 버튼을 disabled="true", 즉 작동하지 않는 상태로 두고 아이디와 비밀번호 유효성 검사를 모두 충족했을 때 disabled="false"로 변경되도록 구현하고 싶었으나 실패했다 ㅎ 다시 시도해볼 수도 있으니 일단 참고하기 좋은 블로그 링크를 남겨둔다.

 

참고

https://stackoverflow.com/questions/14750078/style-disabled-button-with-css

https://habitual-history.tistory.com/entry/프로젝트-닥터마틴-로그인-버튼-활성화-feat-비동기의-굴레

https://www.delftstack.com/ko/howto/react/disable-button-in-react/

 

 

회원가입 시 바로 로그인 되도록 구현하기

const addHandler = (e) => {
    const newUser = {
      id: uuidv4(),
      userId,
      userPw,
      userName,
    };

    const isAllValid = onChangeUserIdHandler() === true && onChangeUserPwHandler() === true && userId && userPw && userName
    
    // 회원가입 성공
    if (isAllValid) {
      e.preventDefault();
    
      dispatch(__signUp(newUser));
      navigate("/")
      alert("가입완료");

      // 회원가입 성공하면 따로 로그인할 필요 없이 바로 로그인됨
      localStorage.clear();
      localStorage.setItem("id", newUser.id)
    }

로그인의 로직이 로그인을 하면 DB에서 일치하는 아이디와 비밀번호를 찾아서 그 계정의 id 값을 로컬스토리지에 저장하는 것이었는데 이것을 이용해서 회원가입하면 따로 로그인할 필요 없이 바로 로그인이 되고 메인페이지로 이동하도록 구현했다.

 

회원가입했을 때 로컬스토리지에 uuid로 생성한 id를 어떻게 넘겨줄 수 있을까 고민했었는데 그냥 간단하게 newUser.id를 가져오면 되는 거였다!

 

 

내가 수정하려는 댓글에만 input 띄우기

원래는 컴포넌트 하나에서 useRef를 사용해서 input 태그에 연결을 하고 [수정] 버튼을 클릭했을 때 그 댓글만 input창을 display:block;로 바꿔주려고 했었다. 근데 어디에 있는 수정 버튼을 누르든 매번 가장 아래에 위치한 댓글의 input 창만 display:block;으로 전환되었다. 팀원들과 계속 해결하려다가 결국 포기하고 튜터님께 찾아갔는데, 가장 아래에 있는 댓글에만 input 창이 뜨는 이유는 map을 돌린 안에 ref가 있었기 때문에 map을 돌다가 가장 밑에 있는 input에 도착(?)한 거 같다.

 

// Comments.jsx
<Wrap>
  {comment.map((co) => {
    return (
      <UpdateComment key={co.id} comment={co}/>
    );
  })}
</Wrap>

이 문제를 해결하기 위해서 Comments 컴포넌트 안에 UpdateComment라는 컴포넌트를 하나 더 만들어서 일단 comments 데이터를 map 돌린 co를 props로 전달했다.

 

const UpdateComment = ({comment}) => {

    const changeInput = useRef();
    const userComment = useRef();

    const changeButtonHandler = (id) => {
      changeInput.current.style = "display:block"
      userComment.current.style = "display:none"
    };

    return (
        <div>
          <span ref={userComment}>{comment.comment}</span>
          <input style={{display: "none"}} ref={changeInput} />
          <span id='comment'>
            <button
              type='button'
              onClick={changeButtonHandler}>
              수정
            </button>
        </div>
    );
};

이렇게 하위 컴포넌트를 만들면 컴포넌트마다, 즉 각 댓글마다 input에 useRef를 하나씩 생성하기 때문에 해당 댓글 수정 버튼을 클릭했을 때 그 댓글에만 input 창을 띄우는 게 가능한 거 같다.

 

 

useInput Custom Hook으로 useState 초기값까지 설정하기

const useInput = (initialValue) => {
    const [value, setValue] = useState(initialValue);
    
    const handler = (e) => {
        setValue(e.target.value);
    };
    
    return [value, setValue, handler];
};

useInput이라는 커스텀 훅을 만들어서 초기값까지 설정해주고 싶다면 useInput을 실행할 때 인자로 초기값을 넘겨받으면 된다.

 

const [value, setValue, onChangeValueHandler] = useInput("초기값입니다");
console.log(value)

실제로 useInput을 사용할 때는 useInput 소괄호 안에 초기값을 넣고 console로 value를 찍어 보면 "초기값입니다"가 뜨는 것을 볼 수 있다.

 

 

thunk 함수 import할 때는 꼭 중괄호를 쓰자!!

import { __uploadPosts } from "../../redux/modules/postsSlice";

디테일 페이지에서 데이터를 불러오는 것이나 삭제 기능은 모두 정상적으로 작동하는데 새 글 등록 기능만 안 돼서 팀원들과 거의 한 시간을 해결하느라 고생했다. [등록하기] 버튼을 눌렀을 때 콘솔에 Cannot read properties of undefined (reading 'type')라는 에러가 떠서 검색해 봤는데도 특별한 정보를 찾을 수 없었다. 모든 코드를 놓치지 않고 살펴봤다고 생각했는데 문제는 import 부분에 있었다!! 모듈 파일에서 thunk 함수를 import할 때 중괄호에 넣지 않아서 문제가 생긴 거였다. 중괄호만 하나 넣어주니 바로 정상적으로 작동했다. 

 

 


회고

오늘은 로그인 페이지 마저 구현하고 팀원들의 문제도 같이 해결하며 시간을 보냈다. 비밀번호를 암호화해서 저장할까 싶어 구글링을 해봤더니 코드가 너무 길고 복잡해서 아직 내 능력 밖의 일이라고 판단되어 포기했다. 오늘도 많은 대부분의 실패와 약간의 성공이 있었는데 로그인 버튼을 disabled를 설정하려다가 실패했고, 로그인 페이지와 회원가입 페이지를 url 하나를 같이 쓰면서 컴포넌트만 번갈아 보여주는 식으로 구현해 보려다가 실패했다. 

 

성공한 일도 얘기해 보자면 회원가입할 때 자동 로그인되도록 구현한 것과 useRef 사용해서 특정 댓글에만 input 띄우기도 성공했다. 그리고 input 입력 문제도 해결했다. 이렇게 적다보니 꽤나 생산적인 하루였던 거 같다. 오늘은 크리스마스 당일인데도 모든 팀원들이 zep에 접속해서 각자의 역할을 수행하고 문제가 생기면 다 같이 해결하기 위해 회의하기도 했다. 피곤하기도 하지만 이렇게 팀원들과 함께 하며 배우는 과정이 즐겁다. 이것도 나중에 가면 다 추억이 될 거라고 생각한다~

 

댓글