Ad

Triggering Specific Function On State Change

I'm trying to trigger a button to bounce when button is clicked and I'm trying to overcome a few things mentioned below:

  1. How do I stop useSpring to only execute when click = true (also on load)? A follow up question for this is. true is temporary how can I make it so that it reverts back to false after the animation is done or after x ms.
  2. How do I stop it from executing animation everytime useState() changes in Input?
  3. How to improve animation bounce to look more smooth? (optional)

Edit jovial-hodgkin-9xp9u

export default function App() {
  const [click, setClick] = useState(false);
  const [input, setInput] = useState("");
  const clicked = useSpring({
    to: [{ transform: "scale(0.95)" }, { transform: "scale(1)" }],
    from: { transform: "scale(1)" },
    config: {
      mass: 1,
      tension: 1000,
      friction: 13
    }
  });

  const getInput = e => {
    setInput(e.target.value);
  };
  return (
    <div className="App">
      <Input placeholder="type here" onChange={getInput} />
      <animated.div style={clicked}>
        <Button style={{ width: "300px" }} onClick={() => setClick(true)}>
          Click me
        </Button>
      </animated.div>
    </div>
  );
}
Ad

Answer

I played around your code. I found a way to do it. First of all you should add a condition to useSpring to only play the animation if click is true. Secondly you should revert click back to false after the animation completed. I used timeout for the reverting part in this code.

export default function App() {
  const [click, setClick] = useState(false);
  const [input, setInput] = useState("");
  const clicked = useSpring({
    to: click
      ? [{ transform: "scale(0.95)" }, { transform: "scale(1)" }]
      : [{ transform: "scale(1)" }],
    from: { transform: "scale(1)" },
    config: {
      mass: 1,
      tension: 1000,
      friction: 13
    }
  });

  const getInput = e => {
    setInput(e.target.value);
  };

  const handleClick = () => {
    setClick(true);
    setTimeout(() => setClick(false), 700);
  };

  return (
    <div className="App">
      <Input placeholder="type here" onChange={getInput} />
      <animated.div style={clicked}>
        <Button style={{ width: "300px" }} onClick={handleClick}>
          Click me
        </Button>
      </animated.div>
    </div>
  );
}

https://codesandbox.io/s/focused-joliot-lk68o

Ad
source: stackoverflow.com
Ad