【问题标题】:Animation resets states of child components动画重置子组件的状态
【发布时间】:2021-12-08 13:10:05
【问题描述】:

我有一个成帧器运动组件(我也尝试过 Stitches components),它根据 useState 变量在视图之间进行动画处理:

const [visible, setVisible] = useState(true);

<motion.div
    animate={visible ? "one" : "two"}
    variants={{
      one: {
        transform: "translateX(0%)",
        opacity: 1
      },
      two: {
        transform: "translateX(100%)",
        opacity: 0
      }
    }}
  >
  // children
</motion.div>

子组件被包装在上下文中,问题是每次触发动画时它们的状态都会重置。

我尝试在当前范围之外声明动画组件。在其当前范围内,它会重置除我的 AuthProvider 上下文中的“currentUser”状态之外的所有内容的状态。在范围之外,它也会重置“currentUser”。为简洁起见,我决定不包含原始代码。

Here 是最小可重复性。如果您在输入中键入内容,然后单击切换按钮,则输入将丢失。

【问题讨论】:

    标签: javascript reactjs framer-motion


    【解决方案1】:

    DummyInputComponent 应该是无状态的,使用上下文提供的值,并且还有一个从上下文传递的 onChange 处理函数

    类似这样的:

    export function AuthProvider({ children }) {
      const [dummyValue, setDummyValue] = useState(null);
    
      const handlechange = (e) => {
        setDummyValue(e.target.value);
      };
    
      const value = {
        dummyValue,
        onChange: handlechange
      };
    
      const DummyInputComponent = () => {
        return <input value={value.dummyValue || ""} onChange={value.onChange} />;
      };
    
      return (
        <AuthContext.Provider value={value}>
          <DummyInputComponent />
        </AuthContext.Provider>
      );
    }
    

    Working CodeSandbox

    【讨论】:

    • 我明白了...这适用于我提供的示例,但在我的真实应用程序中,我正在处理多个嵌套组件和上下文,感觉这会让它变得非常混乱。在那种情况下你会推荐同样的方法吗?
    • 很难判断。如果您真的想在有输入的组件中保留状态处理,另一种解决方法是使用 sessionstorage 或 localstorage 在由帧运动引起的重新渲染中保留输入值。这不是最佳的,但它有效。我仍在调查为什么成帧器运动会导致这种情况,希望能找到更好的解决方案,但到目前为止还没有运气。
    • 我想这可能行得通。是的,我一直在努力寻找遇到同样问题的人,有点迷失在谷歌上。但是感谢您的尝试,我真的很感激。
    【解决方案2】:

    我知道这通常用于性能调整,但我最终通过使用记忆化避免了由帧运动引起的重新渲染(据说):

    const Memoized = React.memo(({ children }) => {
      const [visible, setVisible] = useState(true);
    
     return (
      <motion.div
        animate={visible ? "one" : "two"}
        variants={{
          one: {
            transform: "translateX(0%)",
            opacity: 1
          },
          two: {
            transform: "translateX(100%)",
            opacity: 0
          }
        }}
      >
        {children}
      </motion.div>
     );
    });
    

    我不知道这是否是一个好方法,所以我将保持打开状态。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-24
      • 2019-09-16
      • 2019-11-27
      • 2021-03-14
      • 2018-10-17
      • 2021-06-29
      相关资源
      最近更新 更多