在平时的业务开发中,基于Antd基础组件的二次封装,可以使我们事半功倍,大大提升开发效率。今天分享一个简单的二次封装组件—AutoLoadingButton

件如其名,我们希望得到这样一个Button,当传给它的onClick返回一个Promise时,他能自动呈现loading状态直到resolve或reject发生。

话不多说,上代码:

  1. import React from 'react';
  2. import { Button } from 'antd';
  3. import { ButtonProps } from 'antd/lib/button';
  4. class AutoLoadingButton extends React.Component<ButtonProps> {
  5. state = { loading: false }
  6. handleClick = async (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
  7. const { onClick } = this.props;
  8. if (onClick) {
  9. try {
  10. this.setState({ loading: true });
  11. await onClick(e);
  12. } catch(e) {
  13. throw e;
  14. } finally {
  15. this.setState({ loading: false });
  16. }
  17. }
  18. }
  19. render() {
  20. return <Button
  21. loading={this.state.loading} // 放在{...props}前,当props传入loading是,可以被覆盖
  22. {...this.props}
  23. onClick={this.handleClick} // 放在{...props}后,保证不被覆盖
  24. />
  25. }
  26. }
  27. /* 以下为测试用例 */
  28. function waitms(ms: number) {
  29. return new Promise(function(resolve) {
  30. setTimeout(resolve, ms);
  31. })
  32. }
  33. export default function() {
  34. return <div>
  35. <AutoLoadingButton onClick={waitms.bind(undefined, 1000)}>auto loading</AutoLoadingButton>
  36. </div>
  37. }

听说用React hooks写出来更优雅:

  1. function AutoLoadingButton(props: ButtonProps) {
  2. const [loading, setLoading] = useState(false);
  3. async function handleClick(e: React.MouseEvent<HTMLElement, MouseEvent>) {
  4. const { onClick } = props;
  5. if (onClick) {
  6. try {
  7. setLoading(true)
  8. await onClick(e);
  9. } catch (e) {
  10. throw e;
  11. } finally {
  12. setLoading(false)
  13. }
  14. }
  15. }
  16. return <Button loading={loading} {...props} onClick={handleClick} />
  17. }

以上,就实现了一个简单的AutoLoadingButton。

如何在项目中用起来:

  1. // import { Button } from 'antd';
  2. import Button from 'components/AutoLoadingButton'; // 直接替换Antd Button即可,完美兼容