All files / src/switch/_example SwitchAsyncExample.jsx

40% Statements 12/30
60% Branches 6/10
41.67% Functions 5/12
40% Lines 12/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99          1x                         2x 2x 2x                                       2x 2x     2x     2x 2x 2x                 2x                                               2x                                
import React, { useState, useRef, useEffect } from "react";
import { Switch } from "@tencent/tea-component/lib/switch";
import { Modal } from "@tencent/tea-component/lib/modal";
 
export default function SwitchAsyncExample() {
  return (
    <>
      <p>
        <AsyncSwitch block={false} />
      </p>
      <p>
        <AsyncSwitch block />
      </p>
    </>
  );
}
 
function AsyncSwitch({ block }) {
  const [checked, loading, change] = useAsyncCheck(block, 1000);
  const blockText = block ? "模拟操作失败" : "模拟操作成功";
  return (
    <Switch
      value={checked}
      loading={loading}
      disabled={loading}
      onChange={value => change(value)}
    >
      {loading ? "请稍候..." : blockText}
    </Switch>
  );
}
 
// 这里用 React Hooks 实现,使用 class 的同学可以自行改造
/**
 * @param {boolean} block 是否模拟失败情形
 * @param {number} timeout 模拟的异步时长
 * @returns {[boolean, boolean, (checked: boolean) => {}]}
 */
function useAsyncCheck(block, timeout) {
  // 选中和 loading 态
  const [checked, setChecked] = useState(false);
  const [loading, setLoading] = useState(false);
 
  // 当前执行中的任务
  const taskRef = useRef(null);
 
  // 组件 unmount 的时候清理当前任务
  useEffect(
    () => () => {
      Iif (taskRef && taskRef.current) {
        taskRef.current.cancel();
        taskRef.current = null;
      }
    },
    []
  );
 
  // 处理切换逻辑
  const change = async newChecked => {
    // 先切目标状态,给用户操作反馈
    setChecked(newChecked);
    setLoading(true);
 
    // 创建切换异步任务
    const task = simulateAsyncTask(block, timeout);
    // 任务挂载起来,可以取消之
    taskRef.current = task;
 
    // 执行异步任务
    try {
      await task.run();
    } catch (err) {
      // 失败了恢复到原来的勾选状态
      setChecked(checked);
      Modal.error({ message: "切换失败", description: err.message });
    } finally {
      // 无论成功失败,都退出 loading 态,并清理任务引用
      taskRef.current = null;
      setLoading(false);
    }
  };
 
  return [checked, loading, change];
}
 
function simulateAsyncTask(block, timeout) {
  let timer;
  return {
    cancel: () => clearTimeout(timer),
    run: () =>
      new Promise((resolve, reject) => {
        timer = setTimeout(
          () => (!block ? resolve() : reject(new Error("blocked!"))),
          timeout
        );
      }),
  };
}