본문 바로가기
프론트엔드로 가는 길/portfolio 제작 여정기 👩🏻‍💻

UGSM_Step page 데이터 저장

by woody-j 2023. 12. 23.

 

내가 짠 코드

1.  userAddInfo

const UserAddInfo = () => {
  const [userData, setUserData] = useState<UserData>({ nickname: "", birth: "", gender: "" });
  const [step, setStep] = useState(1);
  const [phone, setPhone] = useState("");
  
  // 휴대폰 인증번호
  const [phoneAuthNumber, setPhoneAuthNumber] = useState("");
  
// 휴대폰 번호 입력
  const handlePhoneChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setPhone(event.target.value);
  };

  // 휴대폰 인증번호 입력
  const handlePhoneAuthChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setPhoneAuthNumber(event.target.value);
  };
  
// 전화번호 서버 전송
  const phoneAuthPost = async () => {
    try {
      const phoneAuth = { phoneNumber: phone };
      await axios.post("주소/api/verification-code", phoneAuth);
    } catch (error) {
      console.log(error);
    }
  };
  
// 번호인증 서버 전송
  const phoneAuthPut = async (phoneAuthNumber: string) => {
    try {
      await axios.put(`주소/api/verification-code/${phoneAuthNumber}`);
    } catch (error) {
      console.log(error);
    }
  };
  
// 유저데이터 서버 전송
  const userDataPost = async (userData: UserData) => {
    try {
      await axios.post(`주소/api/???/${phoneAuthNumber}`, userData);
    } catch (error) {
      console.log(error);
    }
  };

 

React.ChangeEvent<HTMLInputElement> : input 요소의 값이 변경될 때 발생하는 이벤트에 대한 타입

1)  step 단계
2) 유저데이터(nickname, birth, gender) 전송
3) 휴대폰 인증 번호 전송
: 휴대폰 인증 번호를 PUT으로 전송한 이유는 인증번호가 새로 저장되는 것이아니라 "미인증"에서 "인증"으로 상태가 변한다.

 

 return (
    <>
      <Wrapper>
        <ContentBox>
          <PreviousButton onClick={handlePreviousStepChange} step={step} />
        </ContentBox>
        {step === 1 ? (
          <Nickname userData={userData} setUserData={setUserData} />
        ) : step === 2 ? (
          <Gender userData={userData} setUserData={setUserData} />
        ) : step === 3 ? (
          <PhoneNumber phone={phone} onChange={handlePhoneChange} />
        ) : (
          <PhoneNumberAuth phone={phone} phoneAuth={phoneAuthNumber} onChange={handlePhoneAuthChange} />
        )}
      </Wrapper>
      <NextButton onClick={handleNextStepChange} step={step} />
    </>
  );

 

const handleNextStepChange = () => {
    if (step === 3) {
      phoneAuthPost();
    } else if (step === 4) {
      phoneAuthPut(phoneAuthNumber);
      userDataPost(userData);
    }
    updateStep(step + 1);
  };
1) 각 스텝에 해당되는 컴포넌트를 보여준다
2) 이에 따라 필요한 데이터 전달
3) 스텝 3의 경우, 폰 번호 데이터 전송 (post)
4) 스텝 4의 경우 폰 인증번호 (get)와 유저 데이터 전송 (post)

Step 단계마다 컴포넌트를 보여주는 것이 이뻐보이지 않는다.

2.  Nickname

1) 작성하는 데이터 userData state에 저장

실시간으로 한글자 한글자 타이핑 치면서 업데이트 되는 것이 효율적인가 생각이 들었다. blur후 데이터가 업데이트 되는 것은 어떨까

닉네임 작성하는 부분이 짧아서 괜찮겠지만, 길어지면 문제가 좀 되지않을까?

const Nickname: React.FC<UserDataProps> = ({ userData, setUserData }) => {
  const handleNicknameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setUserData((prevUserData) => ({ ...prevUserData, nickname: event.target.value }));
  };

  return (
    <>
      <Wrapper>
        <Question firstLine="반가워요!" secondLine="어떻게 불러드릴까요?" />
        <InputType
          type="text"
          value={userData.nickname}
          placeholder="닉네임을 입력해주세요"
          onChange={handleNicknameChange}
          text="* 2~16자의 한글, 영문, 숫자만 사용해주세요"
        />
      </Wrapper>
    </>
  );
};

3.  Gender 

생일도 포함이 되지만 gender라는 이름은 맞지 않다

const Gender: React.FC<UserDataProps> = ({ userData, setUserData }) => {
  const [gender, setGender] = useState<string>("");
  //생일
  const handleBirthdayChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setUserData({ ...userData, birth: event.target.value });
  };
  //성별 선택
  const handleGenderChange = (selectedGender: string) => {
    setUserData({ ...userData, gender: selectedGender });
    setGender(selectedGender);
  };
1) 생일 경우에는 선택 후, 바로 userData저장하고 userData.birth로 value를 설정
2) 성별의 경우, gender 선택 후 보여지는 button css를 위해 따로 gender state를 만듦

 

button css를 보여주기위해 추가적으로 gender를 만드는 거 말고 다른 방법이 없을까 고민이 됐다.

그리고, 다음페이지로 이동했다가 돌아오니까 클릭했던 것이 풀려버리는 문제가 발생했다.

interface TypeButtonProps {
  type: string;
  setType: (type: string) => void;
  selectedType: string;
}

const Button = styled.button<{ $selected: boolean }>`
  flex-grow: 1;
  border-radius: 15px;
  height: 60px;
  background-color: #fff;
  /* color theme으로 수정 */
  border: 1px solid ${({ $selected }) => ($selected ? "#0F62FE" : "#A2A9AD")};
  color: ${({ $selected }) => ($selected ? "#0F62FE" : "#A2A9AD")};
`;

function TypeButton({ type, setType, selectedType }: TypeButtonProps) {
  return (
    <Button $selected={type === selectedType} onClick={() => setType(type)}>
      {type}
    </Button>
  );
}
  return (
    <Wrapper>
      <Question firstLine="oo님의" secondLine="생일과 성별을 확인해주세요" />
      <InputType type="date" value={userData.birth} onChange={handleBirthdayChange} label="생일" />
      <label>성별</label>
      <TypeButtonBox>
        <TypeButton type="남자" setType={(type) => handleGenderChange(type)} selectedType={gender} />
        <TypeButton type="여자" setType={(type) => handleGenderChange(type)} selectedType={gender} />
      </TypeButtonBox>
    </Wrapper>
  );
};

 

코드 수정

① Step 단계마다 컴포넌트를 보여주는 것이 이뻐보이지 않는다.

=> && 연산자를 사용하여 조건이 참일 때만 해당 요소를 렌더링하도록 했다!

{step === 1 && <Nickname userData={userData} setUserData={setUserData} />}
        {step === 2 && <Gender userData={userData} setUserData={setUserData} />}
        {step === 3 && <PhoneNumber phone={phone} onChange={handlePhoneChange} />}
        {step === 4 && (
          <PhoneNumberAuth phone={phone} phoneAuth={phoneAuthNumber} onChange={handlePhoneAuthChange} />
        )}

 

 

④ 그리고, 다음페이지로 이동했다가 돌아오니까 클릭했던 것이 풀려버리는 문제가 발생했다.

=> 기본값으로 userData.gender를 사용

 const [gender, setGender] = useState<string>(userData.gender || "");