作为Web开发人员,我们都知道按钮在应用程序中的重要性。无论是提交表单,触发操作还是进行API调用,按钮在推动用户交互中都起着至关重要的作用。但是,当涉及到在按钮点击中添加异步代码(例如执行API调用并等待结果)时,我们倾向于变得懒惰或忘记添加。
用户的问题
您是否曾经遇到过按钮在等待异步操作完成时遇到或不反应的情况?它发生在我们最好的人身上。在编码的热量中,很容易忘记在我们的按钮中添加必要的加载状态,使用户感到困惑和沮丧。
在本文中,我们将探索一种简单而强大的方法来增强按钮功能,特别是要简化加载状态。尽管我们将使用React作为我们的示例框架,但这些技术可以应用于任何Web开发框架。
将加载状态添加到按钮
让我们开始了解在单击按钮中添加异步,连续运行代码的典型工作流程:
- 用户单击按钮,启动操作。
- 我们将加载状态设置为true,表明按钮正在进行。
- 我们开始执行异步代码,例如进行API调用。
- 操作完成后,我们将加载状态更新为false。
但是,每当我们需要合并此功能时,我们都会发现自己编写重复的样板代码。此外,忽略加载状态可能会导致用户体验差。
简化按钮加载
要应对这些挑战并使按钮加载体验更容易处理,我们需要直观的API和更少的样板代码。
让我们看一下React中的典型按钮代码段:
import { Button } from 'Button';
const APIButton = () => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const handleClick = () => {
setLoading(true);
setError('');
submitFormToBackend()
.then(() => {
setLoading(false);
})
.catch((err) => {
setError(err);
});
}
return (
<>
<Button
onClick={handleClick}
className={`${loading && 'btn-loading'} ${error && 'btn-error'}`}
disabled={loading}
>
Label
</Button>
{error && <div>{error}</div>}
</>
);
}
此代码演示了一种常见模式,在处理按钮点击时,我们可以手动管理加载和错误状态。但是,这似乎是太多的样板(我很懒惰写一些额外的钥匙打击)。
用增强的组件简化按钮加载
为了使按钮加载状态更易于管理,我们可以修改按钮组件本身。目标不是使我们的按钮代码混乱,而是以仍然可以使我们的代码可读和可维护的方式进行补充。
想象将按钮视为具有禁用,忙碌和错误状态的输入字段。
让我们增强按钮组件以内部处理加载并简化我们的代码:
interface ButtonProps {
loading?: boolean;
disabled?: boolean;
onClick?: (e: MouseEvent<HTMLButtonElement>) => (void | Promise<void>);
}
export const Button: FunctionComponent<ButtonProps> = (props) => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
const clickResult = props.onClick?.(e);
// If our onClick returns a Promise, handle the loading states
if (clickResult instanceof Promise) {
setLoading(true);
setError('');
clickResult
.catch((err) => {
if (err.status === 403) {
setError('Unauthorized');
}
})
.finally(() => {
setLoading(false);
});
}
}
const buttonClasses = classnames('btn', {
'btn-loading': loading,
'btn-error': !!error
});
let buttonEl = (
<button
disabled={props.disabled || loading}
className={buttonClasses}
role={loading ? "progressbar" : ""}
>
{props.children}
</button>
);
if (error) {
buttonEl = (
<Tooltip content={error} color="danger">
{buttonEl}
</Tooltip>
);
}
return buttonEl;
}
使用此增强的按钮组件,我们有一种更强大,更直观的方式来管理加载和错误状态。该组件在内部照顾加载状态,使我们能够专注于编写清洁剂和更简洁的代码。
实现增压按钮
现在,让我们看看我们的新和改进按钮如何简化我们的代码:
import { Button } from 'Button';
const APIButton = () => {
const handleClick = () => {
return submitFormToBackend()
.catch((err) => {
if (err.status === 403) {
throw new Error('Unauthorized');
}
});
};
return (
<Button onClick={handleClick}>
Label
</Button>
);
}
通过简单地返回我们的handleClick
函数的承诺,我们就可以轻松地合并加载和错误状态。这是一个附加的单词,可以大大简化我们的代码并改善用户体验。
控制加载和错误状态
我们构建的承诺的按钮组件使我们有效地处理不同的方案:
- 如果我们不想在没有承诺的情况下显示加载状态,我们可以简单地省略从处理功能的承诺返回。
- 如果我们要显示加载状态,但没有错误工具提示,我们可以返回诺言,但要捕获错误,以防止按钮组件捕获它们。
结论
在本文中,我们探讨了如何通过简化加载状态来增强按钮。通过增强我们的按钮组件,我们可以简化过程,减少样板代码并提供更平滑的用户体验。
让我们参与讨论:
- 您可以通过这种方法找到任何问题吗?
- 让我知道您最喜欢的迷你黑客,这些小黑客可以简化您的开发过程。