• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    해결됨

react hooks 포트폴리오 리펙토링 질문

24.05.10 04:10 작성 조회수 51

0

import { Modal } from "antd";
import DaumPostcodeEmbed from "react-daum-postcode";
import * as S from "./BoardWrite.style";
import UploadImage from "../../../commons/uploadImage/uploadImage.container";
import { v4 as uuidv4 } from "uuid";
import { useBoard } from "../../../commons/hooks/customs/useBoard";
import { useCheckedId } from "../../../commons/hooks/customs/useCheckedId";
import { useForm } from "react-hook-form";
import { useToggle } from "../../../commons/hooks/customs/useToggle";
import { useEffect, useState } from "react";
import type { IBoardWriteProps } from "./BoardWrite.types";
import { useAuth } from "../../../commons/hooks/customs/useAuth";

export interface Iform {
  writer: string;
  password: string;
  title: string;
  contents: string;
  boardAddress: {
    zipcode: string;
    address: string;
    addressDetail: string;
  };
  youtubeUrl: string;
  images: string[];
}

export default function BoardWrite(props: IBoardWriteProps): JSX.Element {
  useAuth();

  const { id } = useCheckedId("boardId");
  const { onClickWrite, onClickEdit, onChangePassword } = useBoard({
    boardId: id,
  });
  const [files, setFiles] = useState(["", "", ""]);

  // const [isActive] = useToggle();
  const [isOpenModal, modalToggle] = useToggle();

  // 게시글 작성 안했을시 오류 보여주는 state

  const [Error] = useState("");

  const { register, handleSubmit, setValue } = useForm<Iform>();

  useEffect(() => {
    if (props.data) {
      setValue("writer", props.data.fetchBoard.writer ?? "");
      setValue("title", props.data.fetchBoard.title ?? "");
      setValue("contents", props.data.fetchBoard.contents ?? "");
      setValue(
        "boardAddress.zipcode",
        props.data.fetchBoard.boardAddress?.zipcode ?? ""
      );
      setValue(
        "boardAddress.address",
        props.data.fetchBoard.boardAddress?.address ?? ""
      );
      setValue(
        "boardAddress.addressDetail",
        props.data.fetchBoard.boardAddress?.addressDetail ?? ""
      );
      setValue("images", props.data.fetchBoard.images ?? ["", "", ""]);
    }
    const images = props.data?.fetchBoard.images;
    if (images !== undefined && images !== null) setFiles([...images]);
  }, [props.data]);

  const onChangeFiles = (file: string, index: number): void => {
    // file값은 url값 index는 해당하는 number값.
    const newFiles = [...files];
    newFiles[index] = file;
    setFiles(newFiles);
    setValue("images", newFiles);
  };

  return (
    <S.Wrapper>
      <S.BoardTitle>게시글 {props.isEdit ? "수정" : "등록"}</S.BoardTitle>

      <S.WriterSection>
        <S.HalfSection>
          <S.BoardLabel>작성자</S.BoardLabel>
          <S.BoardInput
            type="text"
            defaultValue={props.data?.fetchBoard.writer ?? ""}
            placeholder="작성자를 입력해주세요"
            {...register("writer")}
          />
          <S.Error>{Error}</S.Error>
        </S.HalfSection>

        <S.HalfSection>
          <S.BoardLabel>비밀번호</S.BoardLabel>
          <S.BoardInput
            type="password"
            placeholder="비밀번호를 입력해주세요."
            {...register("password")}
            onChange={onChangePassword}
          />
          <S.Error>{Error}</S.Error>
        </S.HalfSection>
      </S.WriterSection>

      <S.Section>
        <S.BoardLabel>제목</S.BoardLabel>
        <S.BoardInput
          type="text"
          placeholder="제목을 입력해주세요"
          {...register("title")}
        />
        <S.Error>{Error}</S.Error>
      </S.Section>

      <S.Section>
        <S.BoardLabel>내용</S.BoardLabel>
        <S.BoardContents
          id="title"
          placeholder="내용을 입력해주세요"
          {...register("contents")}
        ></S.BoardContents>
        <S.Error>{Error}</S.Error>
      </S.Section>

      <S.Section>
        <S.BoardLabel>주소</S.BoardLabel>
        <S.ZipCodeWrapper>
          <S.ZipCodeInput
            placeholder="07725"
            readOnly
            {...register("boardAddress.zipcode")}
          />
          <S.ZipCodeButton onClick={modalToggle}>
            우편번호 검색
            {/* 모달창의 state를 받아와서 true라면 모달창을 열어준다. */}
            {isOpenModal && (
              <Modal open={isOpenModal}>
                <DaumPostcodeEmbed
                  onComplete={(data) => {
                    setValue("boardAddress.zipcode", data.zonecode);
                    setValue("boardAddress.address", data.address);
                    modalToggle();
                  }}
                />
              </Modal>
            )}
          </S.ZipCodeButton>
        </S.ZipCodeWrapper>

        <S.Address readOnly {...register("boardAddress.address")} />
        <S.Address
          type="text"
          placeholder="상세주소를 입력해주세요"
          {...register("boardAddress.addressDetail")}
        />
      </S.Section>
      <S.Section>
        <S.BoardLabel>유튜브</S.BoardLabel>
        <S.BoardInput
          type="text"
          placeholder="링크를 복사해주세요"
          {...register("youtubeUrl")}
        />
      </S.Section>
      <S.Section>
        <S.BoardLabel>사진 첨부</S.BoardLabel>
        {/* 이미지 업로드 컴포넌트 분리 */}
        <S.ImageWrapper>
          {files.map((el, index) => (
            <UploadImage
              key={uuidv4()}
              files={el} // 여기로 들어온 el값은 ""값 기본값이기 때문에
              index={index}
              onChangeFiles={onChangeFiles}
            />
          ))}
        </S.ImageWrapper>
      </S.Section>

      <S.Section>
        <S.BoardLabel>메인 설정</S.BoardLabel>

        <S.RadioButton type="radio" id="youtube" name="radio-button" />
        <S.RadioLabel htmlFor="youtube">유튜브</S.RadioLabel>

        <S.RadioButton type="radio" id="image" name="radio-button" />
        <S.RadioLabel htmlFor="image">사진</S.RadioLabel>
      </S.Section>
      <S.RegistButton
        onClick={handleSubmit(props.isEdit ? onClickEdit : onClickWrite)}
        isEdit={props.isEdit}
      >
        {props.isEdit ? "수정" : "등록"}하기
      </S.RegistButton>
    </S.Wrapper>
  );
}

포트폴리오 리펙토링을 진행하다가 useForm의 defaultValue를 사용할때 텍스트 데이터는 잘 들어오다가

modal창의 주소 데이터나 images 배열은 제대로 들어오지 않아서 방법을 찾다가 setValue를 이용해서 값을 넣어주는 방법이 있어서 이렇게 작성해봤는데 useEffect를 이용해서 만들어봤는데 setValue는 setState와 같은 기능을 하는것같아서 이런식으로하면 리렌더링의 문제가 없는지 궁금합니다

답변 1

답변을 작성해보세요.

0

안녕하세요! 현민님!

리렌더링은 최소화 하는 것이 좋지만, 리렌더링 1번을 줄이기 위해 전체적인 코드의 복잡도가 높아져 유지보수 및 협업이 어려워진다면 좋은 선택이 아닌 것 같네요!^^
setValue 를 사용하여 코드를 깔끔하게 유지하는게 좋아보여요!