ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Chat GPT로 리액트 컴포넌트 작성해보기
    Study/개발 2023. 2. 9. 00:41

    챗 지피티와의 첫 인사

     

    요즘 유행하는 ChatGPT로 리액트 간단한 리액트 컴포넌트를 작성해보았다.

    ChatGPT를 써 본 소감은 계속 ChatGPT와 티키타카를 해나가야 괜찮은 결과가 나온다는 것이다.

    내가 해본 예시는 아래와 같다.

    (영어는 생각나는대로 했기 때문에 많이 틀렸을테지만 양해 바람)

     

    1. 대화 시작 및 첫 스펙 제시

    리액트 + 타입스크립트를 사용하여 인풋필드와 서밋 버튼이 있는 컴포넌트 작성 요청.

    제출 목록은 인풋 아래에 있고, 제출 버튼을 누르면 목록이 업데이트 되어야함.

    Q. Create an React Typescript code. It should contain an input field and a submit button. when you click submit, the submitted list is updated immediately. submit list is placed under the input.
    import React, { useState } from "react";
    
    interface Props {}
    
    const InputSubmit: React.FC<Props> = () => {
      const [submitList, setSubmitList] = useState<string[]>([]);
      const [inputValue, setInputValue] = useState<string>("");
    
      const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        setSubmitList([...submitList, inputValue]);
        setInputValue("");
      };
    
      return (
        <div>
          <form onSubmit={handleSubmit}>
            <input
              type="text"
              value={inputValue}
              onChange={(e) => setInputValue(e.target.value)}
            />
            <button type="submit">Submit</button>
          </form>
          <ul>
            {submitList.map((value, index) => (
              <li key={index}>{value}</li>
            ))}
          </ul>
        </div>
      );
    };
    
    export default InputSubmit;

    조금 바꾸면 좋을 것 같은 부분이 보이지만, 작동하는 리액트 코드가 작성되었다.

     

    2. Presenter(presentational) container 패턴 적용

    Presenter(presentational) container 패턴 적용을 요청했다.

    이 부분은 바로 안 될 수도 있다고 생각했는데 놀랍게도 바로 분리해준다.

    Q. Can you adopt Presenter-Container pattern to this component?
    // InputSubmit.tsx
    import React, { useState } from "react";
    
    interface Props {
      onSubmit: (value: string) => void;
      submitList: string[];
    }
    
    const InputSubmit: React.FC<Props> = ({ onSubmit, submitList }) => {
      const [inputValue, setInputValue] = useState<string>("");
    
      const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        onSubmit(inputValue);
        setInputValue("");
      };
    
      return (
        <div>
          <form onSubmit={handleSubmit}>
            <input
              type="text"
              value={inputValue}
              onChange={(e) => setInputValue(e.target.value)}
            />
            <button type="submit">Submit</button>
          </form>
          <ul>
            {submitList.map((value, index) => (
              <li key={index}>{value}</li>
            ))}
          </ul>
        </div>
      );
    };
    
    export default InputSubmit;
    // InputSubmitContainer.tsx
    import React, { useState } from "react";
    import InputSubmit from "./InputSubmit";
    
    const InputSubmitContainer: React.FC = () => {
      const [submitList, setSubmitList] = useState<string[]>([]);
    
      const handleSubmit = (value: string) => {
        setSubmitList([...submitList, value]);
      };
    
      return (
        <InputSubmit
          onSubmit={handleSubmit}
          submitList={submitList}
        />
      );
    };
    
    export default InputSubmitContainer;

    뒤에 이 패턴에 대한 설명도 덧붙여준다.

    더보기

    In this example, the InputSubmit component acts as a presenter, responsible for rendering the UI. The InputSubmitContainer component acts as a container, responsible for managing the state and handling the interactions with the InputSubmit component.

    By separating the presentational and container components, you can keep the code cleaner and easier to maintain. You can also reuse the InputSubmit component in other parts of your application without having to recreate the same code.

     

     

    3. Presentaional 컴포넌트를 Pure 컴포넌트로 만들기

    분리는 됐지만, Presentational 컴포넌트가 퓨어한 방식이었으면 좋겠다고 생각

    구구절절한 설명 없이 pure하게 변경 해달라고 요청했다. (이것도 될 줄은 몰랐다.)

    Q. I think it'd be better to make presentational component pure. Can you do this?
    // InputSubmit.tsx
    import React from "react";
    
    interface Props {
      inputValue: string;
      onInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
      onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
      submitList: string[];
    }
    
    const InputSubmit: React.FC<Props> = ({
      inputValue,
      onInputChange,
      onSubmit,
      submitList
    }) => (
      <div>
        <form onSubmit={onSubmit}>
          <input type="text" value={inputValue} onChange={onInputChange} />
          <button type="submit">Submit</button>
        </form>
        <ul>
          {submitList.map((value, index) => (
            <li key={index}>{value}</li>
          ))}
        </ul>
      </div>
    );
    
    export default React.memo(InputSubmit);
    // InputSubmitContainer.tsx
    import React, { useState } from "react";
    import InputSubmit from "./InputSubmit";
    
    const InputSubmitContainer: React.FC = () => {
      const [inputValue, setInputValue] = useState<string>("");
      const [submitList, setSubmitList] = useState<string[]>([]);
    
      const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setInputValue(event.target.value);
      };
    
      const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
        event.preventDefault();
        setSubmitList([...submitList, inputValue]);
        setInputValue("");
      };
    
      return (
        <InputSubmit
          inputValue={inputValue}
          onInputChange={handleInputChange}
          onSubmit={handleSubmit}
          submitList={submitList}
        />
      );
    };
    
    export default InputSubmitContainer;

    이전보다 좀 더 구색이 갖춰져 보인다.

    핸들러들과 상태들이 Container로 올라왔고, presentaional 컴포넌트는 prop만 받고 memo까지 적용되었다.

     

    4. 다 잘 되는 것은 아니다.

    지금 만들어진 내용은 인풋값 변경 시 제출 목록도 항상 업데이트한다.

    이 부분을 성능 개선해달라고 요청했을 때, React.memo의 prop 비교를 이용해서 개선을 시도하나 제대로 동작하지 않는다.

    Q. Great. But this example addresses a performance problem. whenever the inputValue changes, the whole presentational component re-renders due to prop change. How would you fix this?
    const InputSubmit: React.FC<Props> = React.memo(
      ({ inputValue, onInputChange, onSubmit, submitList }) => (
        <div>
          <form onSubmit={onSubmit}>
            <input type="text" value={inputValue} onChange={onInputChange} />
            <button type="submit">Submit</button>
          </form>
          <ul>
            {submitList.map((value, index) => (
              <li key={index}>{value}</li>
            ))}
          </ul>
        </div>
      ),
      // props에서 submitList만 비교하기 때문에 input값 변경 시 인풋도 업데이트가 되지 않는다.
      (prevProps, nextProps) => {
        return prevProps.submitList === nextProps.submitList;
      }
    );

    (물론 내 요청이 별로였을 수도 있다.)

    몇번의 추가 질문을 통해 수정 후 테스트 작성도 요청해 봤더니, 그럴싸하지만 틀린 테스트를 주었다.

    // Input.test.tsx
    import React from "react";
    import { render, fireEvent } from "@testing-library/react";
    import Input from "./Input";
    
    describe("Input", () => {
      it("renders an input field and a submit button", () => {
        const { getByLabelText, getByText } = render(<Input />);
    
        expect(getByLabelText("Input")).toBeInTheDocument();
        expect(getByText("Submit")).toBeInTheDocument();
      });
    
      it("calls the onSubmit prop when the submit button is clicked", () => {
        const onSubmit = jest.fn();
        const { getByText } = render(<Input onSubmit={onSubmit} />);
    
        fireEvent.click(getByText("Submit"));
    
        expect(onSubmit).toHaveBeenCalled();
      });
    });
    인풋에 라벨은 안만들어 줬는데 라벨텍스트를 통한 텍스트를 하고 있다 😢

     

    5. 결론

    개인적으로는 얘를 아직 신뢰하지는 못하겠다. 하지만 애매한 네이밍 컨벤션을 추천 부탁하거나, 전혀 모르는 언어로 간단한 코드를 작성할 때는 지금도 쓸 만 한 것 같다.

    코딩할 줄 아는 심심이가 생긴 느낌이다. 심심할 때 페어코딩할 수 있는 심심이. 어쩌면 얘를 통해 내가 시도해보지 않은 방식의 인사이트를 얻을 수 있을지도 모르겠다!

     

    알아서 오늘 코딩 요약까지 해주는 녀석..

     

    728x90

    'Study > 개발' 카테고리의 다른 글

    그림 그려주는 AI - Mid Journey  (0) 2023.03.18
    VS code에서 ChatGPT 사용  (8) 2023.02.19
    타입스크립트 5.0 베타 요약  (1) 2023.02.06
    타입스크립트 기초 강의 추천  (0) 2023.01.29
    Vercel 사용해보기  (0) 2022.09.21
Designed by Tistory.