개인프로젝트: VarGen(3.0)-useQuery 입력값 받기

윤뿔소·2023년 3월 10일
0

저번에 이어서 이번엔 제출버튼을 누르면 그 답으로 오게 만들어보겠다.

구성요소

저번에 이어서 필요한 재료는 form-input 컴포넌트, submit 버튼, text를 담아줄 상태, 제출 핸들러가 필요하다.

text를 담아줄 상태

useState를 써서 상태를 선언해주자.

const [promptValue, setPromptValue] = useState("");

이런 식으로 해서 파라미터 prompt에 인수로 넣어줄 텍스트 데이터를 만들어준다.

UI 만들기

우선 텍스트의 값을 전달하는 모양새이기 때문에 form 태그를 이용해서 작성하겠다.

    <form onSubmit={handleSubmit}>
      <input type="text" value={promptValue} onChange={(e) => setPromptValue(e.target.value)} />
      <button type="submit">Submit</button>
    </form>
    {/* <ChatResponse prompt={`Create 10 login related variable names with React`} /> */}
    {promptValue && <ChatResponse prompt={promptValue} />}

제출 핸들러는 이후 기술할 거지만 일단 handleSubmit으로 작성했고, promptValue 상태를 가져와 onChange를 넣어 텍스트가 입력되고 promptValue가 있다면 API 요청을 하여 목록을 가져오도록 했다.

handleSubmit

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
  };

event에 타입 설정하고, 새로고침 방지하는 코드를 작성하려고 했다.

근데 입력하던 도중 어떻게 코드를 전개해야할지 고민했다.

작성 중 걸림돌

입력하다 생각이 들었는데 handleSubmit이란게 따로 없어도 되지 않나 싶었다. 왜냐면 {promptValue && <ChatResponse prompt={promptValue} />}부분에서 promptValue이 설정되면 결괏값이 나오도록 했기 때문이다.

그러면 핸들러를 빼고 그냥 해도 되지 않느냐? 싶지만 다시 생각해보면 매 입력때마다 API 호출을 한다는 뜻이다;; 그리고 만약 추후에 직접 입력을 하든, 내가 드롭다운 메뉴로 변수 생성을 위한 환경 설정을 매번 할 때마다 API 호출이 간다면 사이트 성능이 떨어질 것이어서 마음이 아플 것이다. 또 API 호출이 계속 이뤄지기에 내 지갑도 마음이 아플 것이다.

해결?

다양한 해결법을 생각해봤다.

  1. 매 입력을 받는 input 상태를 제작해서 promptValue 상태는 제출할 때만 쓰기
  2. lodash의 debounce 라이브러리를 써서 500ms마다 실행되게 하기
  3. inputonBlur 이벤트를 삽입해 포커스가 해제될 때 이벤트 설정하기

등등이 있는데 1번이 가장 깔끔하고, 상태의 변경이 제일 적어 쓸데없는 리렌더링이 덜 날 거 같아 1번으로 했다.

수정 코드

상태 추가, handleSubmit 수정, input 태그 속성 수정

  const queryClient = new QueryClient();
  const [inputValue, setInputValue] = useState("");
  const [promptValue, setPromptValue] = useState("");

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (inputValue !== "") {
      queryClient.invalidateQueries("chatResponse");
      setPromptValue(inputValue);
    }
  };

  const ChatResponse = ({ prompt }: ChatResponseProps) => {
    const { data, isLoading } = useQuery(["chatResponse", prompt], () => getChatResponse(prompt));

    return isLoading ? <div>Loading...</div> : <div>{data?.resText}</div>;
  };

  return (
    <>
      <form onSubmit={handleSubmit}>
        <input type="text" value={inputValue} onChange={(e) => setInputValue(e.target.value)} />
        <button type="submit">Submit</button>
      </form>
      {promptValue && <ChatResponse prompt={promptValue} />}
    </>
  );
  1. 입력되는 관련 데이터는 inputValue 상태로 모두 수정
  2. handleSubmit 조건이 충족되면 setPromptValue 부분을 inputValue로 수정
  3. 추가로 isLoading을 넣어 로딩되는지 직접적으로 보여주기

나중에 ChatResponseuseQuery 전용 컴포넌트로 분리를 해야겠다.

성공!

이제 다음 목차에선 직접 입력이 아닌 드롭다운 메뉴로 선택하여 더 편하게 변수를 생성하게 만들게 디자인 해보겠다.

profile
코뿔소처럼 저돌적으로

6개의 댓글

comment-user-thumbnail
2023년 3월 12일

완성이 거의 다돼가고 있군요 !! 저도 나중에 디바운스 써봐야겠어요 ㅎㅎ 잘봅고갑니다

답글 달기
comment-user-thumbnail
2023년 3월 12일

화이팅입니다 !!!

답글 달기
comment-user-thumbnail
2023년 3월 12일

지갑과 마음이 아프면 큰일나죠... 저도 그 마음 잊지않고 개발하겠습니다

답글 달기
comment-user-thumbnail
2023년 3월 12일

api호출 무한 루프때문에 아마존에서 요금 폭탄 맞는 분들이 많다던데, 주의해야 겠네요. 미리 알고 처방을 하셨다니 다행입니다!

답글 달기
comment-user-thumbnail
2023년 3월 12일

끝이 없군요 작업이 !!

답글 달기
comment-user-thumbnail
2023년 3월 12일

오... 해결방법을 여러가지 써주셨는데 lodash에 debounce라는 라이브러리도 되게 유용해보여요 🤩

답글 달기