Skip to content

Instantly share code, notes, and snippets.

@alexeyraspopov
Created September 9, 2020 16:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexeyraspopov/0c52b74e66ed7a7395e5f5d4d79c8071 to your computer and use it in GitHub Desktop.
Save alexeyraspopov/0c52b74e66ed7a7395e5f5d4d79c8071 to your computer and use it in GitHub Desktop.
import * as React from 'react';
import { useState } from 'react';
import { useHistory } from 'react-router-dom';
import useAsyncCallback from './useAsyncCallback';
export default function LoginPage() {
let history = useHistory();
return (
<article>
{/* какой-то контент, всё что угодно на странице логина */}
{/* предположим, при успешном логине уходим в корень приложения */}
<LoginForm onSuccess={() => history.push('/')} />
{/* футер, ещё больше контента страницы например */}
</article>
);
}
function LoginForm({ onSuccess }) {
let [username, setUsername] = useState('');
let [password, setPassword] = useState('');
let [response, performSubmit] = useAsyncCallback(async (event) => {
event.preventDefault();
await login(username, password);
onSuccess();
}, [password, username]);
return (
<form onSubmit={performSubmit}>
<input type="text"
value={username}
onChange={event => setUsername(event.target.value)}
/>
<input type="password"
value={password}
onChange={event => setPassword(event.target.value)}
/>
{response.type === 'Failure' ? (
<p className="error">{response.error.message}</p>
) : null}
<button
type="submit"
disabled={response.type === 'Pending'}
>
Log in
</button>
</form>
)
}
async function login(username, password) {
// Запрос на сервер или что угодно для логина
}
// https://gist.github.com/alexeyraspopov/75f467f2f8776b5591a8d1cbc9c15258#declarative-action-callback
let idle = Object.freeze({ type: 'Idle' });
let pending = Object.freeze({ type: 'Pending' });
function useAsyncCallback(fn, deps) {
let [response, setResponse] = useState(idle);
let action = useCallback(
(...args) => {
setResponse(pending);
return Promise.resolve(fn(...args))
.then(result => {
setResponse({ type: 'Success', result })
return result;
})
.catch(error => {
setResponse({ type: 'Failure', error })
throw error;
});
},
deps,
);
return [response, action];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment