【问题标题】:How do I mount/unmount a component in React with a keystroke?如何通过按键在 React 中挂载/卸载组件?
【发布时间】:2020-11-02 01:41:39
【问题描述】:

我正在制作一个在键盘按下时呈现 3d 对象的应用程序。我希望这些对象在 2-3 秒后或动画播放完毕后消失。

这是一个处理按键逻辑的组件:

const Selector = () => {
  const [selector, setSelector] = useState(null);
  useEffect(() => {
    function setupKeyLogger() {
      document.onkeydown = function (e) {
        console.log(e);
        switch (e.keyCode) {
          case 65:
            setSelector('SpinningCube');
            break;
          case 83:
            setSelector('SmallCube');
            break;
          default:
            break;
        }
      };
    }
    setupKeyLogger();
  });
  switch (selector) {
    case 'SpinningCube':
      return (
        <>
          <SpinningCube />
        </>
      );
    case 'SmallCube':
      return (
        <>
          <SmallCube />
        </>
      );
    default:
      return <></>;
  }
};

现在,当我按下两个不同的键时,它正在两个对象&lt;SpinningCube /&gt;&lt;SmallCube /&gt; 之间切换。但是,如果我向某个键发送垃圾邮件,它只会在初始按键时呈现组件。我希望它在每次按下键时重新渲染并重新启动组件上的动画,即使它一遍又一遍地重复。我假设我需要一种方法来卸载然后在每次击键时重新安装组件?

我正在使用 Three 和 React Spring 来处理我的动画。

【问题讨论】:

  • 你的效果只能用useEffect(..., [])应用一次
  • 使用安装来控制动画通常听起来是个坏主意。动画更像是一种效果,而不是有状态的东西

标签: javascript reactjs three.js react-spring react-three-fiber


【解决方案1】:

当 props 或 state 发生变化时,组件将重新渲染。当您向按钮发送垃圾邮件时,会设置相同的状态,但不会更改,因此不会发生任何事情。因此,您需要在每次按下时翻转并传递给孩子的另一个参数(强制他们重新渲染)。

const Selector = () => {
  const [selector, setSelector] = useState(null);
  const [forceRender, setForceRender] = useState(0);
  const forceAnimation = (selected) => {
    setSelector(selected);
    setForceRender(++forceRender);
  };

  useEffect(() => {
    function setupKeyLogger() {
      document.onkeydown = function (e) {
        console.log(e);
        switch (e.keyCode) {
          case 65:
            forceAnimation('SpinningCube');
            break;
          case 83:
            forceAnimation('SmallCube');
            break;
          default:
            break;
        }
      };
    }
    setupKeyLogger();
  });

  switch (selector) {
    case 'SpinningCube':
      return (
        <key={forceRender}> // if this doesn't work, I'd try passing it to a React.Fragment or div instead
          <SpinningCube />
        </>
      );
    case 'SmallCube':
      return (
        <key={forceRender}>
          <SmallCube />
        </>
      );
    default:
      return <></>;
  }
};

【讨论】:

  • @charlieyin 在 useEffect 中,你还应该返回一个函数来清理 onkeydown 事件。
猜你喜欢
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
  • 2021-10-08
  • 2018-10-11
  • 1970-01-01
  • 2021-04-26
  • 2016-02-15
  • 2018-04-08
相关资源
最近更新 更多