如何在反应按钮上动态显示加载器

How to dynamically show loader on react button

下面是我的代码

 <button
          className="btn"
          id={index}
          onClick={() =>
            `Make an API call`
            )
          }
        >
          {loader && index =={"Dont know how to add button ID here to show loader"}? (
            <i class="fas fa-spinner fa-spin login-spin"></i>
          ) : (
            "Add To Cart"
          )}
        </button>

我有一堆按钮,我计划在用户单击特定按钮时显示加载程序,同时我向后端发布请求,我已经将索引作为每个按钮的 ID,但我无法访问按钮 ID 以显示加载程序符号, 我不知道如何在不点击的情况下访问 BTN id PS:i 在函数内部而不是 React 组件

我猜你可以直接添加,判断满足显示加载图标的条件就可以了

您可以使用以下方法来实现此目的

  1. 定义一个状态来设置选中的按钮id,比如 selectedButtonId
  2. 点击按钮时,应设置为所选按钮的 ID 然后在你的 API 调用成功后,它应该被重置为 默认值。
  3. 然后将按钮的索引(id)与定义的状态进行比较 步骤 (1) 以显示适用的加载程序。

这是一个利用上述几点的示例代码 - 但只是更改了按钮标签而不是加载图标

export default function App() {
  const [selectedBtnId, setSelectedBtnId] = useState(-1);
  const buttons = [{ id: 1 }, { id: 2 }, { id: 3 }];
  const handleClick = id => setSelectedBtnId(id);
  return (
    <div>
      {buttons.map(({ id }) => (
        <button id={id} key={id} onClick={() => handleClick(id)}>
         {selectedBtnId === id ? 'Loading': 'Click Me'}
        </button>
      ))}
    </div>
  );
}

onClick 事件对象访问按钮 id

示例:

const clickHandler = e => {
  const { id } = e.target;
  // id is button id
};

<button id={0} onClick={clickHandler}>Click Me</button>

将此与一些与当前正在加载的按钮 ID 相关联的加载状态结合起来。使用当前 loading 状态按钮 ID 匹配任何特定按钮的 id

const [loadingId, setLoadingId] = useState({});

...

setLoadingId((ids) => ({
  ...ids,
  [id]: true
}));

...

<button type="button" id={0} onClick={clickHandler}>
  {loadingId[0] ? <Spinner /> : "Button Text Here"}
</button>

完整示例:

const mockFetch = () =>
  new Promise((resolve) => {
    setTimeout(() => resolve(), 3000);
  });

function App() {
  const [loadingId, setLoadingId] = useState(null);

  const clickHandler = async (e) => {
    const { id } = e.target;
    setLoadingId(ids => ({
      ...ids,
      [id]: true
    }));
    try {
      await mockFetch();
    } catch {
      // ignore
    } finally {
      setLoadingId(ids => ({
        ...ids,
        [id]: false
      }));
    }
  };

  return (
    <div className="App">
      <button type="button" id={0} onClick={clickHandler}>
        {loadingId[0] ? "loading..." : 0}
      </button>
      <button type="button" id={1} onClick={clickHandler}>
        {loadingId[1] ? "loading..." : 1}
      </button>
      <button type="button" id={2} onClick={clickHandler}>
        {loadingId[2] ? "loading..." : 2}
      </button>
      <button type="button" id={3} onClick={clickHandler}>
        {loadingId[3] ? "loading..." : 3}
      </button>
      <button type="button" id={4} onClick={clickHandler}>
        {loadingId[4] ? "loading..." : 4}
      </button>
    </div>
  );
}

演示

我最好为接收索引并执行其所需操作的按钮使用单独的组件

function LoadingButton({id}) {
   const [isLoading,setIsLoading] = useState(false);
   if (isLoading) return (<i class="fas fa-spinner fa-spin login-spin"></i>)
   return ( 
        <button
          className="btn"
          id={id}
          onClick={() =>
             setIsLoading(true)
             MakeApiRequest().then(result=>setIsLoading(false))
            )
          }
        >
          "Add to Cart"
        </button>
    )

}

这是一个更好的选择,因为它允许您拥有多个独立的加载按钮,您可以点击其中的一些按钮,每个按钮都会显示一个微调器。

那你就可以像这样使用了

<LoadingButton id={index}/>