Dhiraj Baruah
Dhiraj Baruah

Reputation: 192

ReactJS: onClick function executes before clicking button

The function SendCred() executes the page is loading, but I want this to be called when the user clicks the <button>. What should I do?

 import React,{useState} from "react";

    export default function Signup(props){

      const sendCred=()=>{
        console.log("test")
      };


      return (
        <div className="row container">
          <button onClick={sendCred()}> Activate Laser </button>
        </div>
      );

    };

Upvotes: 3

Views: 2736

Answers (5)

Max
Max

Reputation: 2036

You just shouldn't call that function, just pass it directly to onClick listener

 import React,{useState} from "react";

    export default function Signup(props){

      const sendCred=()=>{
        console.log("test")
      };


      return (
        <div className="row container">
          <button onClick={sendCred}> Activate Laser </button>
        </div>
      );

    };

It can also be memoized with useCallback hook functionality(docs)

import React,{useState} from "react";

   export default function Signup(props){

     const sendCred = useCallback(() => {
       console.log("test")
     });


     return (
       <div className="row container">
         <button onClick={sendCred}> Activate Laser </button>
       </div>
     );

   };

Upvotes: 2

Muhammad Ibrar
Muhammad Ibrar

Reputation: 107

It is happening because when html template render on browser then sendCred() immediately execute the function. If you want to execute on click then you need to pass it onClick={sendCred()}

import React,{useState} from "react";

    export default function Signup(props){

      const sendCred=()=>{
        console.log("test")
      };


      return (
        <div className="row container">
          <button onClick={sendCred}> Activate Laser </button>
        </div>
      );

    };

Hope so it will help you to solve problem. Here reference document to check example https://reactjs.org/docs/handling-events.html

Upvotes: 0

Greggory Wiley
Greggory Wiley

Reputation: 981

This happened to me because I was trying to pass a prop / parameter to my onClick function. The first part of Dacre Denny's answer on this question made that clear to me.

The reason I was doing this is probably a common cause of this issue / Stack result.

I needed to access a dom element within a different component that was not available via documentQuerySelector, so I was attempting to pass a ref from a useRef hook down into the component and then act on it via the onClick function. The function executed at load and not on onClick. The pattern I ended up using to deal with this was, as follows.

/** Parent Component has access to props or ref and onClick Function **/

import { useRef } from 'react';
const formRef = useRef(); // ref has dom elements need accessing

const onClickFunction=()=>{
var inputs = formRef.current.querySelectorAll('input')
 /* Act on ref or props here via onclick function */
 };
 return(
 <ComponentWithPropsForOnClick formRef={formRef} />
 <ComponentNeedingOnClick onClickFunction={onClickFunction}/>
 )

/** Child component calling function with props or ref**/

export const SSDIBelow = ({ onClickFunction}) =>{

  <button onClick={onClickFunction}>
}

Upvotes: 1

Eliecer Chicott
Eliecer Chicott

Reputation: 581

You are executing the function sendCred by calling it inside the onClick using "sendCred()". That event listener receives a function so you should assign sendCred alone.

Like this:

 return (
   <div className="row container">
     <button onClick={sendCred}>Activate Laser</button>
   </div>
 );

For the function you should know that you will receive the event that may be useful for you.

 const sendCred = useCallback((event) => {
   console.log('This is the click event:', event);
   console.log("test");
 });

As the onClick receives a function you can use clousures to take advantage of having some value you want sent along with the event.

The code will look something like this:

   import React, {useState} from "react";

   export default function Signup(props) {

     const sendCred = useCallback((value) => (event) => {
       console.log("I have a value:", value);
       console.log("I have an event:", event);
     });

     return (
       <div className="row container">
         <button onClick={sendCred('Laser')}>Activate Laser</button>
         <button onClick={sendCred('Engine')}>Activate Engine</button>
       </div>
     );
   };

That works because you return a function with value available for it to use and when the button is clicked the second function is executed with the event as a parameter.

hope it helps! ;)

Upvotes: 0

Dacre Denny
Dacre Denny

Reputation: 30390

The sendCred function is being called directly, when the result of your functional component is being evaluated and returned:

{/* The sendCred() function is being evaluated during render, and the 
    result of sendCred is being passed to the onClick prop */
<button onClick={sendCred()}> Activate Laser </button>

To achieve the desired behavior, consider specifying the value passed to onClick as a callback function that wraps a call to sendCred() (ie an arrow function as shown below). By doing this, the arrow function will be passed to onClick and, when a user click invokes onClick, the supplied arrow function will be called which will in turn cause sendCred() to be called:

export default function Signup(props){

  const sendCred=()=>{
    console.log("test")
  };

  return (
    <div className="row container">
      {/* Wrap sendCred() with an arrow function, and pass the arrow
          function to onClick as the callback to be invoked for user 
          click events on button */}
      <button onClick={ () => sendCred() }> Activate Laser </button>
    </div>
  );
};

Alternatively, you could also just pass the sendCred function directly to onClick - the key here is to ensure that you do not include a parenthesis pair (as you currently have done), as doing so will cause sendCred to be invoked during render:

{ /* Omit the () after sendCred */ }  
<button onClick={ sendCred }> Activate Laser </button>

Upvotes: 5

Related Questions