Last active
December 28, 2021 18:35
-
-
Save andrelandgraf/2434bc466ef62d870db0ce6264a709a8 to your computer and use it in GitHub Desktop.
working with URLSearchParams in remix.run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Form as RemixForm } from 'remix'; | |
import type { FC } from 'react'; | |
import type { FormProps, Request } from 'remix'; | |
type FormReqBody = { method: 'get' | 'post' | 'put' | 'delete' } & Record<string, string>; | |
export async function parseURLSearchParams(request: Request): Promise<Partial<FormReqBody>>; | |
export async function parseURLSearchParams<ReqBody>(request: Request): Promise<Partial<ReqBody & FormReqBody>>; | |
export async function parseURLSearchParams<ReqBody>(request: Request): Promise<Partial<ReqBody & FormReqBody>> { | |
const queryString = await request.text(); | |
const searchParams = new URLSearchParams(queryString); | |
const body: any = {}; | |
const entries = Array.from(searchParams.entries()); | |
entries.forEach(([key, value]) => { | |
body[key] = value; | |
}); | |
body.method = (searchParams.get('_method') ?? request.method).toLowerCase(); | |
return body as Partial<ReqBody & FormReqBody>; | |
} | |
const Form: FC<FormProps> = ({ children, method, ...props }) => { | |
const notAllowedMethod = method !== 'get' && method !== 'post'; | |
return ( | |
<RemixForm | |
{...props} | |
// only 'get' and 'post' are allowed for html form | |
method={notAllowedMethod ? 'post' : method} | |
> | |
{ | |
// need this hidden input because regular forms don't all for the delete method https://docs.remix.run/v0.17/api/remix/#form-method | |
notAllowedMethod ? <input type="hidden" name="_method" value={method} /> : null | |
} | |
{children} | |
</RemixForm> | |
); | |
}; | |
export default Form; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface LoginForm { | |
email: string; | |
password: string; | |
} | |
const getErrorRoute = (errCode: AuthErrors) => `/auth/login?error=${errCode}`; | |
export const action: ActionFunction = async ({ request }) => { | |
const { method, email, password } = await parseURLSearchParams<LoginForm>(request); | |
if (method !== 'post') { | |
return redirect(getErrorRoute(AuthErrors.internalError)); | |
} | |
const [status, state, resData] = await auth.loginWithPassword(email, password); | |
if (status !== 200 || !resData) { | |
switch (state) { | |
case auth.LoginResStatus.emailRequired: | |
case auth.LoginResStatus.passwordRequired: | |
return redirect(getErrorRoute(AuthErrors.informationMissing)); | |
case auth.LoginResStatus.userNotFound: | |
return redirect(getErrorRoute(AuthErrors.userNotFound)); | |
case auth.LoginResStatus.wrongPassword: | |
return redirect(getErrorRoute(AuthErrors.wrongPassword)); | |
default: | |
return redirect(getErrorRoute(AuthErrors.internalError)); | |
} | |
} | |
return createUserSession(request, resData.token.accessToken, '/dashboard/projects'); | |
}; | |
export default function Login() { | |
const formSubmit = usePendingFormSubmit(); | |
const [email, setEmail] = useState(''); | |
const [password, setPassword] = useState(''); | |
return ( | |
<CenteredContent> | |
<h1>Sign in</h1> | |
<FormContainer> | |
<Form method="post"> | |
<Input | |
type="email" | |
id="email" | |
name="email" | |
autoComplete="username" | |
value={email} | |
handleChange={(v) => setEmail(v)} | |
label="Email" | |
required | |
/> | |
<Password | |
id="password" | |
name="password" | |
autoComplete="current-password" | |
value={password} | |
handleChange={(v) => setPassword(v)} | |
label="Password" | |
required | |
/> | |
<Button type="submit" isLoading={!!formSubmit} primary> | |
Login | |
</Button> | |
</Form> | |
</FormContainer> | |
</CenteredContent> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: This Form component is not needed anymore. The Remix Form component now provides that functionality built-in!