[컴] nextjs commerce 에서 login 의 동작

nextjs commerce 에서 login 의 동작

login button click 시

  1. LoginView 에서 submit button 을 누르면, useLogin을 호출한다.
  2. useLogin 은 현재의 provider에서 auth.useLogin을 가져오고,
  3. useMutationHook 을 호출하면서 그것을 parameter hook 으로 보낸다.
  4. 그러면, useMutationHook에서 hook.useHook을 호출한다. 즉, provider.auth.useLogin.useHook 을 호출하게 되는 것이다.
  1. useHook은 다시 그 안에서, fetch 를 호출하는데, 이안에서 다시 useLogin.fetcher 를 호출하게 된다.
  2. useLogin.fetcher에서 mutation 을 보내게 된다.
// components/auth/LoginView.tsx
...

const LoginView: React.FC = () => {
  ...

  const login = useLogin()

  const handleLogin = async (e: React.SyntheticEvent<EventTarget>) => {
    ...

    try {
      setLoading(true)
      setMessage('')

      // --> packages/commerce/src/auth/use-login.tsx 
      await login({
        email,
        password,
      })
      ...
    } catch ({ errors }) {
      ...
    } finally {
      setLoading(false)
    }
  }

  ...

  return (
    <form
      onSubmit={handleLogin}
      className="w-80 flex flex-col justify-between p-3"
    >
      ...
    </form>
  )
}

export default LoginView
// packages/commerce/src/auth/use-login.tsx 

export type UseLogin<
  H extends MutationHook<LoginHook> = MutationHook<LoginHook>
> = ReturnType<H['useHook']>

export const fetcher: HookFetcherFn<LoginHook> = mutationFetcher

const fn = (provider: Provider) => provider.auth?.useLogin!

const useLogin: UseLogin = (...args) => {

  // --> packages/commerce/src/utils/use-hook.ts
  const hook = useHook(fn)

  // --> packages/commerce/src/utils/use-hook.ts
  return useMutationHook({ fetcher, ...hook })(...args)
}

export default useLogin
// packages/commerce/src/utils/use-hook.ts

export function useHook<
  P extends Provider,
  H extends MutationHook<any> | SWRHook<any>
>(fn: (provider: P) => H) {
  const { providerRef } = useCommerce<P>()
  const provider = providerRef.current
  return fn(provider)
}
...
export function useMutationHook<H extends MutationHook<any>>(
  hook: PickRequired<H, 'fetcher'>
) {
  const fetcher = useFetcher()

  // --> packages/vendure/src/auth/use-login.tsx
  return hook.useHook({

    fetch: useCallback(
      ({ input } = {}) => {

        // --> packages/vendure/src/auth/use-login.tsx
        return hook.fetcher({
          input,
          options: hook.fetchOptions,
          fetch: fetcher,
        })
      },
      [fetcher, hook.fetchOptions]
    ),
  })
}
// packages/vendure/src/auth/use-login.tsx

export default useLogin as UseLogin<typeof handler>

export const handler: MutationHook<LoginHook> = {
  ...
  async fetcher({ input: { email, password }, options, fetch }) {
    if (!(email && password)) {
      throw new CommerceError({
        message: 'A email and password are required to login',
      })
    }

    const variables: LoginMutationVariables = {
      username: email,
      password,
    }

    const { login } = await fetch<LoginMutation>({
      ...options,
      variables,
    })

    if (login.__typename !== 'CurrentUser') {
      throw new ValidationError(login)
    }

    return null
  },
  useHook:
    ({ fetch }) =>{
      return () => {
        const { mutate } = useCustomer()

        return useCallback(
          async function login(input) {

            // --> packages/commerce/src/utils/use-hook.ts
            const data = await fetch({ input })

            await mutate()
            return data
          },
          [fetch, mutate]
        )
      }
    },
}

아래와 같은 graphql 을 보내게 된다.

{"query":"
  mutation login($username: String!, $password: String!) {
    login(username: $username, password: $password) {
      __typename
      ... on CurrentUser {
        id
      }
      ... on ErrorResult {
        errorCode
        message
      }
    }
  }
  ","variables":{"username":"gaedduck@gmail.com","password":"ldldlldfgpassword"}}

See Also

  1. 쿠…sal: [컴][웹] next.js commerce + vendure 서버 실행

댓글 없음:

댓글 쓰기