2

below is my code

 <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>

I have a bunch of buttons and i am planning to show loader if the user click on particular button,at the same time i am posting a request to backend, i have given index as id to each button but i am unable to access the button ID to show the loader symbol, i do not know how to acces BTN id without click PS:i am inside a function not a react component

0

4 Answers 4

3

You can make use of the below approach to achieve this

  1. Define a state to set the selected button id, something like selectedButtonId
  2. On clicking the button, it should be set to the selected button id and then after your API call is success, it should be reset to the default value.
  3. Then compare the index(id) of button with the state defined in step(1) to show the loader as applicable.

Here is a sample code which utilizes the above points - But just changes the button label instead of a loading icon

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>
  );
}
Sign up to request clarification or add additional context in comments.

1 Comment

Hey thanks man, appreciate that, I got the idea how to do that...
2

Access the button id from the onClick event object.

Example:

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

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

Combine this with some loading state that correlates a currently loading button id. Use the current loading state button id to match the id for any specific button.

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

...

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

...

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

Full example:

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>
  );
}

Demo

Edit how-to-dynamically-show-loader-on-react-button

1 Comment

Thanks man, I liked this approach, it's really good....
1

I would better go with a separate component for a button that receives an index and does whatever it wants

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>
    )

}

This is a better option because it allows you to have multiple standalone loading buttons, you can click some of them and each will show a spinner.

Then you can use it like

<LoadingButton id={index}/>

Comments

-1

I guess you can just add it directly and judge that it meets the conditions for displaying the loading icon.

2 Comments

i cannot add directly, because i have 20 odd buttons
Oh oh, what is your judgment condition

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.