【问题标题】:Is there a way to trigger useState hook when the newvalue is same as oldvalue当新值与旧值相同时,有没有办法触发 useState 钩子
【发布时间】:2021-03-14 21:06:54
【问题描述】:

selectedName 发生变化时,我有一个动画要触发,但似乎新值与动画没有触发的先前值相同。在调查之后,钩子唯一的触发器是 newvalue 与以前的 value 不同。有没有办法解决这个问题?

    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

【问题讨论】:

  • 您可以将其更改为对象const [selectedName, setSelectedName] = useState({value: ""});。你可以这样设置:setSelectedName({value: "somevalue"})。这样,即使您将其更新为相同的对象,useEffect 也会触发。
  • 只是为了澄清。您想在 value 改变时触发,或者当有一些事件 可能改变 value 时触发,但不一定要这样做?
  • @codemonkey 它确实解决了关于触发钩子的问题。就我而言,我使用的是 react-transition-group。即使更改后动画似乎仍然没有触发
  • @Mr. Hedgehog 不,我希望钩子触发即使新值与以前的值相同
  • 知道了。所以动画可能与手头的问题无关。如果您可以沙盒化您的应用程序(至少是基本版本),我相信我们可以解决这个问题。

标签: reactjs typescript use-state


【解决方案1】:

您的想法是正确的 - 即使数字相同,每次点击都会触发重新渲染。你做错的唯一一件事是在相同元素的每个渲染上将相同的 key 属性分配给你的 CSSTransition elelemnt。

key 需要是唯一的,因为 React 使用 key prop 来理解组件到 DOM 元素的关系,然后用于reconciliation process。因此,密钥始终保持唯一非常重要,否则 React 很有可能会混淆元素并改变不正确的元素。

无论如何,您确实需要第二个状态变量来触发重新渲染。我们将做一些基本的事情:const [trigger, triggerUpdate] = useState<boolean>(false);。然后你可以像这样触发它:triggerUpdate(!trigger);

当然,最重要的部分是 key 属性

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

请注意,我使用此机制提出了一个独特的key,您不必一定要遵循此示例:

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

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

【讨论】:

  • 非常感谢。我明白。使用new Date().toISOString() as key prop 是否更安全?我假设在这种情况下密钥不会重复。这将如何影响 react DOM 或内存使用。有没有办法破坏前一个,也许反应会自动处理这个?我不完全理解布尔触发部分。每次运行 getRandomNumber 方法时,您都将值从 true 更改为 false,反之亦然。但是我没有看到它在CSSTransistion组件中使用,它怎么知道什么时候更新?
  • @CookieMonster 我只会使用key={Date.now()}
  • trigger 变量不需要在return 方法中使用。只需更新它就会自行触发重新渲染,这就是我们想要的。
  • 啊哈,所以基本上CSSTransition 正在寻找getRandomNumber() 方法的任何变化来触发动画?这似乎有点令人困惑,因为按钮是在CSSTransition Component 之外调用方法和button 组件的按钮。
  • @CookieMonster 不完全是。这并不是说CSSTransition 正在寻找任何东西的任何变化,真的。关键是,每当您更新任何状态变量时,render 函数都会再次运行。因为CSSTransition在里面,所以每次都会渲染。因此,通过创建这个trigger 变量,我们只需强制render 再次运行。当我们这样做时,我们会确保 CSSTransition 每次都有一个唯一的 key 属性。
猜你喜欢
  • 2021-05-15
  • 1970-01-01
  • 2022-12-08
  • 2011-10-13
  • 2020-07-17
  • 2021-10-24
  • 2021-07-13
  • 2010-11-03
  • 1970-01-01
相关资源
最近更新 更多