Search code examples
reactjstypescriptuse-state

Is there a way to trigger useState hook when the newvalue is same as oldvalue


I Have an animation to trigger when selectedName changes, but it seems is the newvalue is same as previous value the animation does not trigger. After looking into it, the hook only trigger is newvalue is different than previous value. Is there a way to fix this?

    const [selectedName, setSelectedName] = useState("");

  useEffect(() => {
    console.log("Change", selectedName)
  }, [selectedName]); 

https://codesandbox.io/s/reactts-text-animation-using-react-transition-group-64gum?file=/src/App.tsx


Solution

  • The idea you had was correct - trigger a re-render on each click even if the number is the same. The only thing you did wrong was assign the same key prop to your CSSTransition element on each render of an identical element.

    The key needs to be unique because React uses the key prop to understand the component-to-DOM Element relation, which is then used for the reconciliation process. It is therefore very important that the key always remains unique, otherwise there is a good chance React will mix up the elements and mutate the incorrect one.

    Anyway, you do need that second state variable to trigger a rerender. We will do something as basic as: const [trigger, triggerUpdate] = useState<boolean>(false);. You can then tigger it like so: triggerUpdate(!trigger);

    And the most important part, of course, is the key prop

      return (
        <div className="App">
          <SwitchTransition mode="out-in">
            <CSSTransition<undefined>
              classNames="fade"
              addEndListener={(node: HTMLElement, done: () => void) => {
                node.addEventListener("transitionend", done, false);
              }}
              key={Math.random()
                .toString(36)
                .replace(/[^a-z]+/g, "")}
            >
              <h1 className="randomNumberText">{rndNumber}</h1>
            </CSSTransition>
          </SwitchTransition>
          <button onClick={() => getRandomNumber()}>Click Me!</button>
        </div>
      );
    
    

    Notice that I use this mechanism to come up with a unique key, you don't have to follow this example necessarily:

    key={Math.random()
                .toString(36)
                .replace(/[^a-z]+/g, "")}
    

    Sandbox: https://codesandbox.io/s/reactts-text-animation-using-react-transition-group-forked-v2cm4?file=/src/App.tsx