2

when I changed the disabled of button from true to false, it messed my onClick, why is that, and how to solve it?

const Component = () => {
  const refrence = React.useRef(null)
  setTimeout(() => {
    refrence.current.disabled = false
  }, 1000);
  const handleClick = () => console.log('clicked')

  return (
    <div>
      <button onClick={handleClick} ref={refrence} disabled>click me</button>
    </div>
  )
}


ReactDOM.render(
  <Component />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script><div id="root"></div>

3
  • 2
    Does this answer your question? Default disabled button click event is not firing on reactjs Commented Jun 10, 2021 at 20:48
  • The button is disabled, and thus, not clickable. Did you mean to conditionally disable the button instead? Commented Jun 10, 2021 at 20:49
  • @DrewReese the problem is that the onClick callback isn't registered if it is re-enabled manually via ref. Commented Jun 10, 2021 at 20:50

1 Answer 1

1

Issue

The issue here is that the React ref is mutating the DOM, but React isn't made aware of this and so Component isn't rerendered with a working button allowing the onClick event to go through. This is the main reason why direct DOM manipulations are considered anti-pattern in React.

Additionally, you are setting a timeout to occur every render, though this would have minimal effect it's still unnecessary and would be considered an unintentional side-effect.

Solution

Use component state and update state in a mounting useEffect hook to trigger a rerender.

const Component = () => {
  const [isDisabled, setIsDisabled] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setIsDisabled(false);
    }, 1000);
  }, []);
  
  const handleClick = () => console.log('clicked');
  
  return (
    <div>
      <button onClick={handleClick} disabled={isDisabled}>click me</button>
    </div>
  )
}

const Component = () => {
  const [isDisabled, setIsDisabled] = React.useState(true);

  React.useEffect(() => {
    setTimeout(() => {
      setIsDisabled(false);
    }, 1000);
  }, []);
  
  const handleClick = () => console.log('clicked');
  
  return (
    <div>
      <button onClick={handleClick} disabled={isDisabled}>click me</button>
    </div>
  )
};

ReactDOM.render(
  <Component />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Sign up to request clarification or add additional context in comments.

Comments

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.