# 3. 회원가입

## 1. 회원가입 로직 작성하기

### ApiService에 signup 메소드 추가

* email : 유저를 구분하기 위함
* name : 서비스 내에서 유저가 사용하는 이름

```tsx
async signup({ email, name, password }: {
  email: string;
  name: string;
  password: string;
}): Promise<string> {
  const { data } = await this.instance.post('/users', {
    email, name, password,
  });
  const { accessToken } = data;
  return accessToken;
}
```

* 대개의 경우 API를 통해 accessToken을 받도록 되어 있음

### Store 생성

로그인과 비슷하게 `SignupFormStore`를 생성

* 서버로 보낼 때 Validation Check 값이 필요하진 않음
* 클라이언트에서만 사용자의 실수를 방지하기 위해 체크

### SignupFormStore를 사용할 수 있는 Hook 생성

```tsx
export default function useSignupFormStore() {
  const store = container.resolve(SignupFormStore);
  return useStore(store);
}
```

<br>

## 2. 회원가입 페이지 UI 구현하기

### SignupForm 컴포넌트 생성

```tsx
export default function SignupForm() {
  const { setAccessToken } = useAccessToken();

  const [{
    email, name, password, passwordConfirmation, valid, error, accessToken,
  }, store] = useSignupFormStore();

  useEffect(() => {
    if (accessToken) {
      setAccessToken(accessToken);
    }
  }, [accessToken]);

  const handleChangeEmail = (value: string) => {
    store.changeEmail(value);
  };
  
  // 중략 
  
  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    store.signup();
  };

  return (
    <Container>
      <h2>회원 가입</h2>
      <form onSubmit={handleSubmit}>
        <TextBox
          label="E-mail"
          placeholder="tester@example.com"
          value={email}
          onChange={handleChangeEmail}
        />
        <TextBox
          label="Name"
          value={name}
          onChange={handleChangeName}
        />
        <TextBox
          label="Password"
          type="password"
          value={password}
          onChange={handleChangePassword}
        />
        <TextBox
          label="Password Confirmation"
          type="password"
          value={passwordConfirmation}
          onChange={handleChangePasswordConfirmation}
        />
        <Button type="submit" disabled={!valid}>
          회원 가입
        </Button>
        {error && (
          <p>회원 가입 실패</p>
        )}
      </form>
    </Container>
  );
}
```

### SignupPage 구현

```tsx
export default function SignupPage() {
  const navigate = useNavigate();

  const [{ accessToken }, store] = useSignupFormStore();

  useEffect(() => {
    store.reset();
  }, []);

  useEffect(() => {
    if (accessToken) {
      store.reset();
      navigate('/signup/complete'); // 회원가입 성공 페이지 
    }
  }, [accessToken]);

  return (
    <SignupForm />
  );
}
```

### SignupCompletePage 구현

회원가입이 완료되었을 때, HomePage로 보내지 않고 따로 회원가입 완료 페이지로 이동

```tsx
export default function SignupCompletePage() {
  return (
    <p>
      회원 가입이 완료되었습니다.
    </p>
  );
}
```

### routes에 추가

```tsx
{ path: '/signup', element: <SignupPage /> },
{ path: '/signup/complete', element: <SignupCompletePage /> },
```

### LoginForm 컴포넌트에 회원 가입 링크 추가

```tsx
<p>
  <Link to="/signup">
    회원 가입
  </Link>
</p>
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://shinjungohs-dev-road.gitbook.io/megaptera-frontend/undefined/week10/signup.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
