繁体   English   中英

将功能组件传递给 React Spring 的 useTransition

[英]Passing Functional Components to React Spring's useTransition

我正在尝试编写一个包含按钮面板的 React 组件,并且每个按钮都需要能够根据应用程序的 state 独立地打开和关闭。 为此,我创建了一个useTransition ,包裹在一个自定义挂钩中,它应该在收到新的 SVG 功能组件时触发转换。

我遇到的问题是,虽然按钮当前正在正确过渡,但我似乎无法让useTransition在收到新组件时将它们换出。 当组件被替换为空数组时,它将删除一个,这是预期的,并且当传入一个新组件时,钩子内的useEffect会触发,但由于某种原因, useTransition不会接收到更改。

我猜它与组件之间的 object 相等性有关,但我不知道如何解决它而不用window.requestAnimationFrame强制更改以设置 Z9ED39E2EA931586B6A985A6942EF7 两次。 这是一个带有最小演示的代码框。

父组件:

import React, { useState } from "react";
import { a } from "react-spring";
import "./styles.css";

import PlaySVG from "./svgs/PlaySVG";
import SaveSVG from "./svgs/SaveSVG";
import SearchSVG from "./svgs/SearchSVG";
import TrashSVG from "./svgs/TrashSVG";

import { useVertTransition } from "./Hooks";

export default function ActionButtons() {
  const svgs = {
    play: <PlaySVG style={{ width: "100%", height: "auto" }} id="play" />,
    search: <SearchSVG style={{ width: "80%", height: "auto" }} id="search" />,
    save: <SaveSVG style={{ width: "80%", height: "auto" }} id="save" />,
    trash: <TrashSVG style={{ width: "80%", height: "auto" }} id="trash" />
  };

  const [actions, setActions] = useState({
    one: svgs.play,
    two: svgs.search,
    three: svgs.trash
  });

  const [slotOne] = useVertTransition(actions.one);
  const [slotTwo] = useVertTransition(actions.two);
  const [slotThree] = useVertTransition(actions.three);

  function buttonHandler() {
    setActions({
      ...actions,
      one: [],
      two: svgs.save
    });
  }

  return (
    <div className="container">
      <div className="panel">
        <div className="button-container">
          {slotOne.map(({ item, props, key }) => (
            <a.button key={key} style={props} onClick={buttonHandler}>
              {item}
            </a.button>
          ))}
        </div>
        <div className="button-container">
          {slotTwo.map(({ item, props, key }) => (
            <a.button key={key} style={props} onClick={buttonHandler}>
              {item}
            </a.button>
          ))}
        </div>
        <div className="button-container">
          {slotThree.map(({ item, props, key }) => (
            <a.button key={key} style={props} onClick={buttonHandler}>
              {item}
            </a.button>
          ))}
        </div>
      </div>
    </div>
  );
}

useVertTransition 钩子:

import React, { useEffect } from "react";
import { useTransition } from "react-spring";

export function useVertTransition(item) {
  useEffect(() => {
    console.log(item);
  }, [item]);

  const vertTransition = useTransition(item, null, {
    from: { transform: "translateY(-20px) rotateX(-90deg)", opacity: 0 },
    enter: { transform: "translateY(0px) rotateX(0deg)", opacity: 1 },
    leave: { transform: "translateY(20px) rotateX(90deg)", opacity: 0 },
    trail: 400,
    order: ["leave", "enter"]
  });

  return [vertTransition];
}

SVG 组件示例:

import React from "react";

function PlaySVG({ style }) {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" style={style} viewBox="0 0 24 24">
      <path d="M7 6L7 18 17 12z" />
    </svg>
  );
}

export default PlaySVG;

你是对的,react-spring 无法检测到按钮之间的区别。 但它不检查项目,它只检查键。 所以你必须为唯一键添加一些东西。 因此,您可能希望将输入从 svg 更改为 object,在 svg 旁边包含一个名称。

  const getSvg = name => ({ name, svg: svgs[name] });

  const [actions, setActions] = useState({
    one: getSvg("play"),
    two: getSvg("search"),
    three: getSvg("trash")
  });

您现在可以添加密钥 function:

 const vertTransition = useTransition(item, svg => svg.name, {

你应该改变渲染:

      {slotOne.map(({ item, props, key }) => (
        <a.button key={key} style={props} onClick={buttonHandler}>
          {item.svg}
        </a.button>
      ))}

现在它按预期工作。 我认为。

https://codesandbox.io/s/usetransition-demo-152zb?file=/src/ActionButtons.js:1253-1437

而且我还学到了一个新技巧,我从来没有使用过 order 属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM