В течение последнего месяца или около того я работал над новой службой, которая предлагает аутентификацию как API, и мне потребовался ввод данных со стороны пользователя во внешнем интерфейсе. Практически каждое веб-приложение в настоящее время позволяет пользователю вводить какую-либо информацию, которая затем используется для выполнения вызовов API от их имени. Извлечение этих данных из форм ввода иногда может быть немного сложным. Одним из моих вариантов использования было разрешение пользователю вводить свои учетные данные перед их входом.
Я уже писал ранее о создании форм с компонентами пользовательского интерфейса материала, но я не хотел полагаться на пользовательский интерфейс материала в этом проекте. Вместо этого я перешел на использование простого HTML и Tailwind CSS для своего стиля. Идея получения информации от пользователя с помощью React аналогична предыдущему посту. Я использовал два input
и один button
с некоторыми слушателями React. Каждый раз, когда любое из полей input
изменяется (что означает, что пользователь вводит информацию), я обновляю переменную состояния, чтобы отслеживать эти данные. Затем, когда пользователь щелкает button
, у меня уже есть введенная информация, сохраненная в состоянии, которая будет использоваться в обработчике button
s onClick
. Ниже приведен простой HTML-код, но через секунду я добавлю немного стиля Tailwind.
export default function SigninPage() {
const [signInEmail, setSignInEmail] = useState('');
const [signInPassword, setSignInPassword] = useState('');
const [errorMessage, setErrorMessage] = useState('');
function handleSignInEmailFieldChange(event) {
event.preventDefault();
setSignInEmail(event.target.value);
}
function handleSignInPasswordFieldChange(event) {
event.preventDefault();
setSignInPassword(event.target.value);
}
async function handleSignIn(event) {
event.preventDefault();
setErrorMessage('');
try {
// Sign In logic using signInEmail and signInPassword state
setErrorMessage('There was an error signing in');
} catch (err) {
// Remediation logic
setErrorMessage('There was an error signing in');
}
}
return(
<div>
<label>Email address</label>
<input
type="email"
placeholder=""
value={signInEmail}
onChange={(e) => handleSignInEmailFieldChange(e)}
/>
<label>Password</label>
<input
type="password"
placeholder=""
value={signInPassword}
onChange={(e) => handleSignInPasswordFieldChange(e)}
/>
<button
onClick={handleSignIn}
>
Sign In
</button>
<p>
{ errorMessage }
</p>
</div>
);
}
Это должно обрабатывать всю логику, связанную с захватом и использованием ввода, предоставленного пользователем, но любому, кто попытается использовать это, вероятно, не понравится результат. Я собираюсь добавить немного стиля "Попутный ветер", но не стесняйтесь использовать его здесь, используя свой собственный стиль.
export default function SigninPage() {
const [signInEmail, setSignInEmail] = useState('');
const [signInPassword, setSignInPassword] = useState('');
const [loading, setLoading] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
function handleSignInEmailFieldChange(event) {
event.preventDefault();
setSignInEmail(event.target.value);
}
function handleSignInPasswordFieldChange(event) {
event.preventDefault();
setSignInPassword(event.target.value);
}
async function handleSignIn(event) {
event.preventDefault();
setErrorMessage('');
setLoading(true);
try {
// Sign In logic using signInEmail and signInPassword state
setErrorMessage('There was an error signing in');
setLoading(false);
} catch (err) {
// Remediation logic
setErrorMessage('There was an error signing in');
setLoading(false);
}
}
return(
<div className="flex flex-col items-center justify-center text-center">
<div className="lg:w-2/5 md:w-3/5 w-4/5">
<label className="mt-6">Email address</label>
<input
type="email"
className="mt-1 w-full rounded-xl border-gray-300 shadow-sm focus:border-purple-500 focus:ring focus:ring-purple-500 focus:ring-opacity-50"
placeholder=""
value={signInEmail}
onChange={(e) => handleSignInEmailFieldChange(e)}
/>
<label className="mt-6">Password</label>
<input
type="password"
className="mt-1 w-full rounded-xl border-gray-300 shadow-sm focus:border-purple-500 focus:ring focus:ring-purple-500 focus:ring-opacity-50"
placeholder=""
value={signInPassword}
onChange={(e) => handleSignInPasswordFieldChange(e)}
/>
<button
className={`
bg-white mt-6 border rounded-xl border-gray-300 p-2 hover:bg-purple-500 hover:text-white
${
loading ? "bg-purple-500 text-white animate-pulse" : ""
}
`}
disabled={loading}
onClick={handleSignIn}
>
Sign In
</button>
<p className="text-red-900">
{ errorMessage }
</p>
</div>
</div>
);
}
Стиль внешнего div
центрирует и выравнивает все в столбце. Второй div
устанавливает ограничение ширины полей для разных размеров экрана. Для label
указано верхнее поле. Поля input
имеют некоторый цвет по краям, когда они находятся в фокусе. Последний p
, содержащий errorMessage
, теперь будет отображать текст красным цветом. Наконец, button
стилизован так, чтобы отображать цвет при наведении курсора или фокусе с некоторым дополнительным стилем после щелчка. Состояние loading
включается при каждом щелчке по button
внутри handleSignIn
и выключается снова, когда логика входа завершается. Пока страница ожидает логики входа, кнопка будет оставаться цветной и пульсировать, показывая пользователю, что что-то происходит за кулисами. Для получения дополнительной информации о классах, пожалуйста, обратитесь к документации Tailwind.